1 // Copyright 2019 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/metrics/frame_sequence_tracker.h"
11 #include "base/memory/raw_ptr.h"
12 #include "base/test/bind.h"
13 #include "base/test/metrics/histogram_tester.h"
14 #include "cc/metrics/compositor_frame_reporting_controller.h"
15 #include "cc/metrics/frame_sequence_tracker_collection.h"
16 #include "components/viz/common/frame_sinks/begin_frame_args.h"
17 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 #include "ui/gfx/presentation_feedback.h"
25 const char* ParseNumber(const char* str, uint64_t* retvalue) {
27 for (; *str >= '0' && *str <= '9'; ++str) {
37 class FrameSequenceTrackerTest : public testing::Test {
39 const uint32_t kImplDamage = 0x1;
40 const uint32_t kMainDamage = 0x2;
42 FrameSequenceTrackerTest()
43 : compositor_frame_reporting_controller_(
44 std::make_unique<CompositorFrameReportingController>(
45 /*should_report_histograms=*/true,
46 /*should_report_ukm=*/false,
47 /*layer_tree_host_id=*/1)),
48 collection_(/*is_single_threaded=*/false,
49 compositor_frame_reporting_controller_.get()) {
50 tracker_ = collection_.StartScrollSequence(
51 FrameSequenceTrackerType::kTouchScroll,
52 FrameInfo::SmoothEffectDrivingThread::kCompositor);
54 ~FrameSequenceTrackerTest() override = default;
56 void CreateNewTracker(FrameInfo::SmoothEffectDrivingThread thread_type =
57 FrameInfo::SmoothEffectDrivingThread::kCompositor) {
58 tracker_ = collection_.StartScrollSequence(
59 FrameSequenceTrackerType::kTouchScroll, thread_type);
62 viz::BeginFrameArgs CreateBeginFrameArgs(
64 uint64_t sequence_number,
65 base::TimeTicks now = base::TimeTicks::Now()) {
66 auto interval = base::Milliseconds(16);
67 auto deadline = now + interval;
68 return viz::BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, source_id,
69 sequence_number, now, deadline, interval,
70 viz::BeginFrameArgs::NORMAL);
73 void StartImplAndMainFrames(const viz::BeginFrameArgs& args) {
74 collection_.NotifyBeginImplFrame(args);
75 collection_.NotifyBeginMainFrame(args);
78 uint32_t DispatchCompleteFrame(const viz::BeginFrameArgs& args,
80 bool has_missing_content = false) {
81 StartImplAndMainFrames(args);
83 if (damage_type & kImplDamage) {
84 if (!(damage_type & kMainDamage)) {
85 collection_.NotifyMainFrameCausedNoDamage(args, false);
87 collection_.NotifyMainFrameProcessed(args);
89 uint32_t frame_token = NextFrameToken();
90 collection_.NotifySubmitFrame(frame_token, has_missing_content,
91 viz::BeginFrameAck(args, true), args);
92 collection_.NotifyFrameEnd(args, args);
95 collection_.NotifyImplFrameCausedNoDamage(
96 viz::BeginFrameAck(args, false));
97 collection_.NotifyMainFrameCausedNoDamage(args, true);
98 collection_.NotifyFrameEnd(args, args);
103 uint32_t NextFrameToken() {
104 static uint32_t frame_token = 0;
105 return ++frame_token;
108 // Check whether a type of tracker exists in |frame_trackers_| or not.
109 bool TrackerExists(FrameSequenceTrackerType type) const {
111 std::make_pair(type, FrameInfo::SmoothEffectDrivingThread::kUnknown);
112 if (type == FrameSequenceTrackerType::kTouchScroll ||
113 type == FrameSequenceTrackerType::kWheelScroll ||
114 type == FrameSequenceTrackerType::kScrollbarScroll) {
115 key = std::make_pair(type,
116 FrameInfo::SmoothEffectDrivingThread::kCompositor);
117 if (!collection_.frame_trackers_.contains(key))
118 key = std::make_pair(type, FrameInfo::SmoothEffectDrivingThread::kMain);
120 return collection_.frame_trackers_.contains(key);
123 bool RemovalTrackerExists(unsigned index,
124 FrameSequenceTrackerType type) const {
125 DCHECK_GT(collection_.removal_trackers_.size(), index);
126 return collection_.removal_trackers_[index]->type() == type;
129 void GenerateSequence(const char* str) {
130 const uint64_t source_id = 1;
131 uint64_t current_frame = 0;
132 viz::BeginFrameArgs last_activated_main_args;
134 const char command = *str++;
135 uint64_t sequence = 0, dummy = 0, last_activated_main = 0;
142 ASSERT_EQ(*str, '(') << command;
143 str = ParseNumber(++str, &sequence);
144 ASSERT_EQ(*str, ')');
150 ASSERT_EQ(*str, '(');
151 str = ParseNumber(++str, &dummy);
152 ASSERT_EQ(*str, ',');
153 str = ParseNumber(++str, &sequence);
154 ASSERT_EQ(*str, ')');
159 ASSERT_EQ(*str, '(');
160 str = ParseNumber(++str, &sequence);
161 ASSERT_EQ(*str, ',');
162 str = ParseNumber(++str, &last_activated_main);
163 ASSERT_EQ(*str, ')');
171 NOTREACHED() << command << str;
176 current_frame = sequence;
177 collection_.NotifyBeginImplFrame(
178 CreateBeginFrameArgs(source_id, sequence));
182 collection_.NotifyFramePresented(
183 sequence, {base::TimeTicks::Now(),
184 viz::BeginFrameArgs::DefaultInterval(), 0});
188 collection_.NotifyPauseFrameProduction();
192 collection_.NotifyImplFrameCausedNoDamage(
193 viz::BeginFrameAck(source_id, sequence, false, 0));
197 auto frame_token = sequence;
198 if (current_frame == 0)
200 auto args = CreateBeginFrameArgs(source_id, current_frame);
201 auto main_args = args;
204 ASSERT_EQ(*str, '(');
205 str = ParseNumber(++str, &sequence);
206 ASSERT_EQ(*str, ')');
208 main_args = CreateBeginFrameArgs(source_id, sequence);
210 collection_.NotifySubmitFrame(
211 frame_token, /*has_missing_content=*/false,
212 viz::BeginFrameAck(args, true), main_args);
217 auto args = CreateBeginFrameArgs(source_id, sequence);
218 if (last_activated_main != 0)
219 DCHECK_EQ(last_activated_main_args.frame_id.sequence_number,
220 last_activated_main);
221 collection_.NotifyFrameEnd(args, last_activated_main_args);
226 last_activated_main_args = CreateBeginFrameArgs(source_id, sequence);
227 collection_.NotifyMainFrameProcessed(last_activated_main_args);
231 collection_.NotifyBeginMainFrame(
232 CreateBeginFrameArgs(source_id, sequence));
236 collection_.NotifyMainFrameCausedNoDamage(
237 CreateBeginFrameArgs(source_id, sequence), true);
246 void ReportMetrics() { tracker_->metrics_->ReportMetrics(); }
248 base::TimeDelta TimeDeltaToReport() const {
249 return tracker_->time_delta_to_report_;
252 unsigned NumberOfTrackers() const {
253 return collection_.frame_trackers_.size();
255 unsigned NumberOfCustomTrackers() const {
256 return collection_.custom_frame_trackers_.size();
258 unsigned NumberOfRemovalTrackers() const {
259 return collection_.removal_trackers_.size();
262 uint64_t BeginImplFrameDataPreviousSequence() const {
263 return tracker_->begin_impl_frame_data_.previous_sequence;
266 uint64_t BeginMainFrameDataPreviousSequence() const {
267 return tracker_->begin_main_frame_data_.previous_sequence;
270 base::flat_set<uint32_t> IgnoredFrameTokens() const {
271 return tracker_->ignored_frame_tokens_;
274 FrameSequenceMetrics::ThroughputData& ImplThroughput(
275 FrameSequenceTracker* tracker) const {
276 return tracker->impl_throughput();
279 FrameSequenceMetrics::ThroughputData& ImplThroughput() const {
280 return tracker_->impl_throughput();
283 FrameSequenceMetrics::ThroughputData& MainThroughput(
284 FrameSequenceTracker* tracker) const {
285 return tracker->main_throughput();
288 FrameSequenceMetrics::ThroughputData& MainThroughput() const {
289 return tracker_->main_throughput();
292 FrameSequenceTracker::TerminationStatus GetTerminationStatus(
293 FrameSequenceTracker* tracker) {
294 return tracker->termination_status_;
296 FrameSequenceTracker::TerminationStatus GetTerminationStatus() {
297 return tracker_->termination_status_;
300 uint32_t NumberOfFramesCheckerboarded() const {
301 return tracker_->metrics_->frames_checkerboarded();
305 std::unique_ptr<CompositorFrameReportingController>
306 compositor_frame_reporting_controller_;
307 FrameSequenceTrackerCollection collection_;
308 raw_ptr<FrameSequenceTracker> tracker_;
311 // Tests that the tracker works correctly when the source-id for the
312 // begin-frames change.
313 TEST_F(FrameSequenceTrackerTest, SourceIdChangeDuringSequence) {
314 const uint64_t source_1 = 1;
315 uint64_t sequence_1 = 0;
317 // Dispatch some frames, both causing damage to impl/main, and both impl and
318 // main providing damage to the frame.
319 auto args_1 = CreateBeginFrameArgs(source_1, ++sequence_1);
320 DispatchCompleteFrame(args_1, kImplDamage | kMainDamage);
321 args_1 = CreateBeginFrameArgs(source_1, ++sequence_1);
322 DispatchCompleteFrame(args_1, kImplDamage | kMainDamage);
324 // Start a new tracker.
327 // Change the source-id, and start an impl frame. This time, the main-frame
328 // does not provide any damage.
329 const uint64_t source_2 = 2;
330 uint64_t sequence_2 = 0;
331 auto args_2 = CreateBeginFrameArgs(source_2, ++sequence_2);
332 collection_.NotifyBeginImplFrame(args_2);
333 collection_.NotifyBeginMainFrame(args_2);
334 collection_.NotifyMainFrameCausedNoDamage(args_2, true);
335 // Since the main-frame did not have any new damage from the latest
336 // BeginFrameArgs, the submit-frame will carry the previous BeginFrameArgs
338 collection_.NotifySubmitFrame(NextFrameToken(), /*has_missing_content=*/false,
339 viz::BeginFrameAck(args_2, true), args_1);
342 TEST_F(FrameSequenceTrackerTest, TestNotifyFramePresented) {
343 collection_.StartSequence(FrameSequenceTrackerType::kCompositorAnimation);
344 collection_.StartSequence(FrameSequenceTrackerType::kMainThreadAnimation);
345 EXPECT_EQ(NumberOfTrackers(), 3u);
347 collection_.StopSequence(FrameSequenceTrackerType::kCompositorAnimation);
348 EXPECT_EQ(NumberOfTrackers(), 2u);
349 EXPECT_TRUE(TrackerExists(FrameSequenceTrackerType::kMainThreadAnimation));
350 EXPECT_TRUE(TrackerExists(FrameSequenceTrackerType::kTouchScroll));
351 // StopSequence should have destroyed all trackers because there is no frame
352 // awaiting presentation.
353 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
356 TEST_F(FrameSequenceTrackerTest, TestJankWithZeroIntervalInFeedback) {
357 // Test if jank can be correctly counted if presentation feedback reports
358 // zero frame interval.
359 const uint64_t source = 1;
360 uint64_t sequence = 1;
361 uint64_t frame_token = sequence;
362 const char* histogram_name =
363 "Graphics.Smoothness.Jank.Compositor.TouchScroll";
364 const base::TimeDelta zero_interval = base::Milliseconds(0);
365 base::HistogramTester histogram_tester;
368 base::TimeTicks args_timestamp = base::TimeTicks::Now();
369 auto args = CreateBeginFrameArgs(source, sequence, args_timestamp);
372 collection_.NotifyBeginImplFrame(args);
373 collection_.NotifySubmitFrame(sequence, false, viz::BeginFrameAck(args, true),
375 collection_.NotifyFrameEnd(args, args);
377 collection_.NotifyFramePresented(
379 /*feedback=*/{args_timestamp, zero_interval, 0});
384 args_timestamp += base::Milliseconds(16.67);
385 args = CreateBeginFrameArgs(source, sequence, args_timestamp);
386 collection_.NotifyBeginImplFrame(args);
387 collection_.NotifySubmitFrame(sequence, false, viz::BeginFrameAck(args, true),
389 collection_.NotifyFrameEnd(args, args);
390 collection_.NotifyFramePresented(
392 /*feedback=*/{args_timestamp, zero_interval, 0});
394 // Frame 3: There is one jank (frame interval incremented from 16.67ms
398 args_timestamp += base::Milliseconds(30.0);
399 args = CreateBeginFrameArgs(source, sequence, args_timestamp);
400 collection_.NotifyBeginImplFrame(args);
401 collection_.NotifySubmitFrame(sequence, false, viz::BeginFrameAck(args, true),
403 collection_.NotifyFrameEnd(args, args);
404 collection_.NotifyFramePresented(
406 /*feedback=*/{args_timestamp, zero_interval, 0});
408 // Frame 4: There is no jank since the increment from 30ms to 31ms is too
409 // small. This tests if |NotifyFramePresented| can correctly handle the
410 // situation when the frame interval reported in presentation feedback is 0.
413 args_timestamp += base::Milliseconds(31.0);
414 args = CreateBeginFrameArgs(source, sequence, args_timestamp);
415 collection_.NotifyBeginImplFrame(args);
416 collection_.NotifySubmitFrame(sequence, false, viz::BeginFrameAck(args, true),
418 collection_.NotifyFrameEnd(args, args);
419 collection_.NotifyFramePresented(
421 /*feedback=*/{args_timestamp, zero_interval, 0});
422 ImplThroughput().frames_expected = 100u;
424 histogram_tester.ExpectTotalCount(
425 "Graphics.Smoothness.Jank.Compositor.TouchScroll", 1u);
427 // There should be only one jank for frame 3.
428 EXPECT_THAT(histogram_tester.GetAllSamples(histogram_name),
429 testing::ElementsAre(base::Bucket(1, 1)));
432 // Base case for checkerboarding: present a single frame with checkerboarding,
433 // followed by a non-checkerboard frame.
434 TEST_F(FrameSequenceTrackerTest, CheckerboardingSimple) {
436 base::HistogramTester histogram_tester;
438 const uint64_t source_1 = 1;
439 uint64_t sequence_1 = 0;
441 // Dispatch some frames, both causing damage to impl/main, and both impl and
442 // main providing damage to the frame.
443 auto args_1 = CreateBeginFrameArgs(source_1, ++sequence_1);
444 bool has_missing_content = true;
445 auto frame_token = DispatchCompleteFrame(args_1, kImplDamage | kMainDamage,
446 has_missing_content);
448 const auto interval = viz::BeginFrameArgs::DefaultInterval();
449 gfx::PresentationFeedback feedback(base::TimeTicks::Now(), interval, 0);
450 collection_.NotifyFramePresented(frame_token, feedback);
452 // Submit another frame with no checkerboarding.
453 has_missing_content = false;
455 DispatchCompleteFrame(CreateBeginFrameArgs(source_1, ++sequence_1),
456 kImplDamage | kMainDamage, has_missing_content);
458 gfx::PresentationFeedback(base::TimeTicks::Now() + interval, interval, 0);
459 collection_.NotifyFramePresented(frame_token, feedback);
461 EXPECT_EQ(1u, NumberOfFramesCheckerboarded());
463 // ImplThroughput().frames_expected is set to 100 since in ReportMetrics(),
464 // in order to report checkerboarding histogram, the minimum frames for
465 // ThroughputMetric is 100.
466 ImplThroughput().frames_expected = 100u;
468 histogram_tester.ExpectTotalCount(
469 "Graphics.Smoothness.Checkerboarding.AllSequences", 1u);
472 // Present a single frame with checkerboarding, followed by a non-checkerboard
473 // frame after a few vsyncs.
474 TEST_F(FrameSequenceTrackerTest, CheckerboardingMultipleFrames) {
476 base::HistogramTester histogram_tester;
478 const uint64_t source_1 = 1;
479 uint64_t sequence_1 = 0;
481 // Dispatch some frames, both causing damage to impl/main, and both impl and
482 // main providing damage to the frame.
483 auto args_1 = CreateBeginFrameArgs(source_1, ++sequence_1);
484 bool has_missing_content = true;
485 auto frame_token = DispatchCompleteFrame(args_1, kImplDamage | kMainDamage,
486 has_missing_content);
488 const auto interval = viz::BeginFrameArgs::DefaultInterval();
489 gfx::PresentationFeedback feedback(base::TimeTicks::Now(), interval, 0);
490 collection_.NotifyFramePresented(frame_token, feedback);
492 // Submit another frame with no checkerboarding.
493 has_missing_content = false;
495 DispatchCompleteFrame(CreateBeginFrameArgs(source_1, ++sequence_1),
496 kImplDamage | kMainDamage, has_missing_content);
497 feedback = gfx::PresentationFeedback(base::TimeTicks::Now() + interval * 3,
499 collection_.NotifyFramePresented(frame_token, feedback);
501 EXPECT_EQ(3u, NumberOfFramesCheckerboarded());
503 // ImplThroughput().frames_expected is set to 100 since in ReportMetrics(),
504 // in order to report checkerboarding histogram, the minimum frames for
505 // ThroughputMetric is 100.
506 ImplThroughput().frames_expected = 100u;
508 histogram_tester.ExpectTotalCount(
509 "Graphics.Smoothness.Checkerboarding.AllSequences", 1u);
512 // Present multiple checkerboarded frames, followed by a non-checkerboard
514 TEST_F(FrameSequenceTrackerTest, MultipleCheckerboardingFrames) {
516 base::HistogramTester histogram_tester;
518 const uint32_t kFrames = 3;
519 const uint64_t source_1 = 1;
520 uint64_t sequence_1 = 0;
522 // Submit |kFrames| number of frames with checkerboarding.
523 std::vector<uint32_t> frames;
524 for (uint32_t i = 0; i < kFrames; ++i) {
525 auto args_1 = CreateBeginFrameArgs(source_1, ++sequence_1);
526 bool has_missing_content = true;
527 auto frame_token = DispatchCompleteFrame(args_1, kImplDamage | kMainDamage,
528 has_missing_content);
529 frames.push_back(frame_token);
532 base::TimeTicks present_now = base::TimeTicks::Now();
533 const auto interval = viz::BeginFrameArgs::DefaultInterval();
534 for (auto frame_token : frames) {
535 gfx::PresentationFeedback feedback(present_now, interval, 0);
536 collection_.NotifyFramePresented(frame_token, feedback);
537 present_now += interval;
540 // Submit another frame with no checkerboarding.
541 bool has_missing_content = false;
543 DispatchCompleteFrame(CreateBeginFrameArgs(source_1, ++sequence_1),
544 kImplDamage | kMainDamage, has_missing_content);
545 gfx::PresentationFeedback feedback(present_now, interval, 0);
546 collection_.NotifyFramePresented(frame_token, feedback);
548 EXPECT_EQ(kFrames, NumberOfFramesCheckerboarded());
550 // ImplThroughput().frames_expected is set to 100 since in ReportMetrics(),
551 // in order to report checkerboarding histogram, the minimum frames for
552 // ThroughputMetric is 100.
553 ImplThroughput().frames_expected = 100u;
555 histogram_tester.ExpectTotalCount(
556 "Graphics.Smoothness.Checkerboarding.AllSequences", 1u);
559 TEST_F(FrameSequenceTrackerTest, ReportMetrics) {
560 base::HistogramTester histogram_tester;
562 // Test that there is no main thread frames expected.
563 ImplThroughput().frames_expected = 100u;
564 ImplThroughput().frames_produced = 85u;
566 histogram_tester.ExpectTotalCount(
567 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll",
569 histogram_tester.ExpectTotalCount(
570 "Graphics.Smoothness.PercentDroppedFrames.MainThread.TouchScroll", 0u);
572 // Test that both are reported.
573 ImplThroughput().frames_expected = 100u;
574 ImplThroughput().frames_produced = 85u;
575 MainThroughput().frames_expected = 150u;
576 MainThroughput().frames_produced = 25u;
578 histogram_tester.ExpectTotalCount(
579 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll",
581 histogram_tester.ExpectTotalCount(
582 "Graphics.Smoothness.PercentDroppedFrames.MainThread.TouchScroll", 1u);
584 // Test that none is reported.
585 MainThroughput().frames_expected = 2u;
586 MainThroughput().frames_produced = 1u;
587 ImplThroughput().frames_expected = 2u;
588 ImplThroughput().frames_produced = 1u;
590 histogram_tester.ExpectTotalCount(
591 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll",
593 histogram_tester.ExpectTotalCount(
594 "Graphics.Smoothness.PercentDroppedFrames.MainThread.TouchScroll", 1u);
596 // Test the case where compositor and main thread have the same throughput.
597 ImplThroughput().frames_expected = 120u;
598 ImplThroughput().frames_produced = 118u;
599 MainThroughput().frames_expected = 120u;
600 MainThroughput().frames_produced = 118u;
602 histogram_tester.ExpectTotalCount(
603 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll",
605 histogram_tester.ExpectTotalCount(
606 "Graphics.Smoothness.PercentDroppedFrames.MainThread.TouchScroll", 2u);
609 TEST_F(FrameSequenceTrackerTest, ReportMetricsAtFixedInterval) {
610 const uint64_t source = 1;
611 uint64_t sequence = 0;
612 base::TimeDelta first_time_delta = base::Seconds(1);
613 auto args = CreateBeginFrameArgs(source, ++sequence,
614 base::TimeTicks::Now() + first_time_delta);
616 // args.frame_time is less than 5s of the tracker creation time, so won't
617 // schedule this tracker to report its throughput.
618 collection_.NotifyBeginImplFrame(args);
619 collection_.NotifyImplFrameCausedNoDamage(viz::BeginFrameAck(args, false));
620 collection_.NotifyFrameEnd(args, args);
622 EXPECT_EQ(NumberOfTrackers(), 1u);
623 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
625 ImplThroughput().frames_expected += 101;
626 // Now args.frame_time is 5s since the tracker creation time, so this tracker
627 // should be scheduled to report its throughput.
628 args = CreateBeginFrameArgs(source, ++sequence,
629 args.frame_time + TimeDeltaToReport());
630 collection_.NotifyBeginImplFrame(args);
631 collection_.NotifyImplFrameCausedNoDamage(viz::BeginFrameAck(args, false));
632 collection_.NotifyFrameEnd(args, args);
633 EXPECT_EQ(NumberOfTrackers(), 1u);
634 // At NotifyFrameEnd, the tracker is removed from removal_tracker_ list.
635 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
638 TEST_F(FrameSequenceTrackerTest, ReportWithoutBeginImplFrame) {
639 const uint64_t source = 1;
640 uint64_t sequence = 0;
642 auto args = CreateBeginFrameArgs(source, ++sequence);
643 collection_.NotifyBeginMainFrame(args);
645 EXPECT_EQ(BeginImplFrameDataPreviousSequence(), 0u);
646 // Call to ReportBeginMainFrame should early exit.
647 EXPECT_EQ(BeginMainFrameDataPreviousSequence(), 0u);
649 uint32_t frame_token = NextFrameToken();
650 collection_.NotifySubmitFrame(frame_token, false,
651 viz::BeginFrameAck(args, true), args);
653 // Call to ReportSubmitFrame should early exit.
654 EXPECT_TRUE(IgnoredFrameTokens().contains(frame_token));
656 gfx::PresentationFeedback feedback;
657 collection_.NotifyFramePresented(frame_token, feedback);
658 EXPECT_EQ(ImplThroughput().frames_produced, 0u);
659 EXPECT_EQ(MainThroughput().frames_produced, 0u);
662 TEST_F(FrameSequenceTrackerTest, MainFrameTracking) {
663 const uint64_t source = 1;
664 uint64_t sequence = 0;
666 auto args = CreateBeginFrameArgs(source, ++sequence);
667 auto frame_1 = DispatchCompleteFrame(args, kImplDamage | kMainDamage);
669 args = CreateBeginFrameArgs(source, ++sequence);
670 auto frame_2 = DispatchCompleteFrame(args, kImplDamage);
672 gfx::PresentationFeedback feedback;
673 collection_.NotifyFramePresented(frame_1, feedback);
674 collection_.NotifyFramePresented(frame_2, feedback);
677 TEST_F(FrameSequenceTrackerTest, MainFrameNoDamageTracking) {
678 const uint64_t source = 1;
679 uint64_t sequence = 0;
681 const auto first_args = CreateBeginFrameArgs(source, ++sequence);
682 DispatchCompleteFrame(first_args, kImplDamage | kMainDamage);
684 // Now, start the next frame, but for main, respond with the previous args.
685 const auto second_args = CreateBeginFrameArgs(source, ++sequence);
686 StartImplAndMainFrames(second_args);
688 uint32_t frame_token = NextFrameToken();
689 collection_.NotifySubmitFrame(frame_token, /*has_missing_content=*/false,
690 viz::BeginFrameAck(second_args, true),
692 collection_.NotifyFrameEnd(second_args, second_args);
694 // Start and submit the next frame, with no damage from main.
695 auto args = CreateBeginFrameArgs(source, ++sequence);
696 collection_.NotifyBeginImplFrame(args);
697 frame_token = NextFrameToken();
698 collection_.NotifySubmitFrame(frame_token, /*has_missing_content=*/false,
699 viz::BeginFrameAck(args, true), first_args);
700 collection_.NotifyFrameEnd(args, args);
702 // Now, submit a frame with damage from main from |second_args|.
703 collection_.NotifyMainFrameProcessed(second_args);
704 args = CreateBeginFrameArgs(source, ++sequence);
705 StartImplAndMainFrames(args);
706 frame_token = NextFrameToken();
707 collection_.NotifySubmitFrame(frame_token, /*has_missing_content=*/false,
708 viz::BeginFrameAck(args, true), second_args);
709 collection_.NotifyFrameEnd(args, args);
712 TEST_F(FrameSequenceTrackerTest, BeginMainFrameSubmit) {
713 // Start with a bunch of frames so that the metric does get reported at the
715 ImplThroughput().frames_expected = 98u;
716 ImplThroughput().frames_produced = 98u;
717 MainThroughput().frames_expected = 98u;
718 MainThroughput().frames_produced = 98u;
720 const char sequence[] =
721 "b(1)B(0,1)n(1)e(1,0)b(2)E(1)B(1,2)s(1)S(1)e(2,1)P(1)";
722 GenerateSequence(sequence);
723 EXPECT_EQ(ImplThroughput().frames_expected, 99u);
724 EXPECT_EQ(MainThroughput().frames_expected, 100u);
726 base::HistogramTester histogram_tester;
729 const char metric[] =
730 "Graphics.Smoothness.PercentDroppedFrames.MainThread.TouchScroll";
731 histogram_tester.ExpectTotalCount(metric, 1u);
732 EXPECT_THAT(histogram_tester.GetAllSamples(metric),
733 testing::ElementsAre(base::Bucket(1, 1)));
736 TEST_F(FrameSequenceTrackerTest, ScrollingThreadMetricCompositorThread) {
737 // Start with a bunch of frames so that the metric does get reported at the
739 ImplThroughput().frames_expected = 100u;
740 ImplThroughput().frames_produced = 100u;
741 MainThroughput().frames_expected = 100u;
742 MainThroughput().frames_produced = 90u;
744 base::HistogramTester histogram_tester;
747 const char metric[] =
748 "Graphics.Smoothness.PercentDroppedFrames.ScrollingThread.TouchScroll";
749 histogram_tester.ExpectTotalCount(metric, 1u);
750 EXPECT_THAT(histogram_tester.GetAllSamples(metric),
751 testing::ElementsAre(base::Bucket(0, 1)));
754 TEST_F(FrameSequenceTrackerTest, ScrollingThreadMetricMainThread) {
755 CreateNewTracker(FrameInfo::SmoothEffectDrivingThread::kMain);
757 // Start with a bunch of frames so that the metric does get reported at the
759 ImplThroughput().frames_expected = 100u;
760 ImplThroughput().frames_produced = 100u;
761 MainThroughput().frames_expected = 100u;
762 MainThroughput().frames_produced = 90u;
764 base::HistogramTester histogram_tester;
767 const char metric[] =
768 "Graphics.Smoothness.PercentDroppedFrames.ScrollingThread.TouchScroll";
769 histogram_tester.ExpectTotalCount(metric, 1u);
770 EXPECT_THAT(histogram_tester.GetAllSamples(metric),
771 testing::ElementsAre(base::Bucket(10, 1)));
774 TEST_F(FrameSequenceTrackerTest, SimpleSequenceOneFrame) {
775 const char sequence[] = "b(1)B(0,1)s(1)S(1)e(1,0)P(1)";
776 GenerateSequence(sequence);
777 EXPECT_EQ(ImplThroughput().frames_expected, 1u);
778 EXPECT_EQ(MainThroughput().frames_expected, 1u);
779 EXPECT_EQ(ImplThroughput().frames_produced, 1u);
780 EXPECT_EQ(MainThroughput().frames_produced, 1u);
783 TEST_F(FrameSequenceTrackerTest, SimpleSequenceOneFrameNoDamage) {
784 const char sequence[] = "b(1)B(0,1)N(1,1)n(1)e(1,0)";
785 GenerateSequence(sequence);
786 EXPECT_EQ(ImplThroughput().frames_expected, 0u);
787 EXPECT_EQ(MainThroughput().frames_expected, 0u);
788 EXPECT_EQ(ImplThroughput().frames_produced, 0u);
789 EXPECT_EQ(MainThroughput().frames_produced, 0u);
791 const char second_sequence[] = "b(2)B(1,2)n(2)N(2,2)e(2,0)";
792 GenerateSequence(second_sequence);
793 EXPECT_EQ(ImplThroughput().frames_expected, 0u);
794 EXPECT_EQ(MainThroughput().frames_expected, 0u);
795 EXPECT_EQ(ImplThroughput().frames_produced, 0u);
796 EXPECT_EQ(MainThroughput().frames_produced, 0u);
799 TEST_F(FrameSequenceTrackerTest, MultipleNoDamageNotifications) {
800 const char sequence[] = "b(1)n(1)n(1)e(1,0)";
801 GenerateSequence(sequence);
802 EXPECT_EQ(ImplThroughput().frames_expected, 0u);
803 EXPECT_EQ(MainThroughput().frames_expected, 0u);
804 EXPECT_EQ(ImplThroughput().frames_produced, 0u);
805 EXPECT_EQ(MainThroughput().frames_produced, 0u);
808 TEST_F(FrameSequenceTrackerTest, MultipleNoDamageNotificationsFromMain) {
809 const char sequence[] = "b(1)B(0,1)N(1,1)n(1)N(0,1)e(1,0)";
810 GenerateSequence(sequence);
811 EXPECT_EQ(ImplThroughput().frames_expected, 0u);
812 EXPECT_EQ(MainThroughput().frames_expected, 0u);
813 EXPECT_EQ(ImplThroughput().frames_produced, 0u);
814 EXPECT_EQ(MainThroughput().frames_produced, 0u);
817 TEST_F(FrameSequenceTrackerTest, DelayedMainFrameNoDamage) {
818 const char sequence[] =
819 "b(1)B(0,1)n(1)e(1,0)b(2)n(2)e(2,0)b(3)N(0,1)n(3)e(3,0)";
820 GenerateSequence(sequence);
821 EXPECT_EQ(ImplThroughput().frames_expected, 0u);
822 EXPECT_EQ(MainThroughput().frames_expected, 0u);
823 EXPECT_EQ(ImplThroughput().frames_produced, 0u);
824 EXPECT_EQ(MainThroughput().frames_produced, 0u);
827 TEST_F(FrameSequenceTrackerTest, DelayedMainFrameNoDamageFromOlderFrame) {
828 // Start a sequence, and receive a 'no damage' from an earlier frame.
829 const char second_sequence[] = "b(2)B(0,2)N(2,1)n(2)N(2,2)e(2,0)";
830 GenerateSequence(second_sequence);
831 EXPECT_EQ(ImplThroughput().frames_expected, 0u);
832 EXPECT_EQ(MainThroughput().frames_expected, 0u);
833 EXPECT_EQ(ImplThroughput().frames_produced, 0u);
834 EXPECT_EQ(MainThroughput().frames_produced, 0u);
837 // This tests when a BeginMainFrame leads to No Damage, after the next Main
838 // Frame has started. This should not crash.
839 TEST_F(FrameSequenceTrackerTest, DelayedMainFrameNoDamageAfterNextMainFrame) {
840 const char sequence[] =
841 "b(1)B(0,1)n(1)e(1,0)E(1)b(2)B(0,2)N(0,1)n(2)N(0,2)e(2,0)";
842 GenerateSequence(sequence);
843 EXPECT_EQ(ImplThroughput().frames_expected, 0u);
844 EXPECT_EQ(MainThroughput().frames_expected, 0u);
845 EXPECT_EQ(ImplThroughput().frames_produced, 0u);
846 EXPECT_EQ(MainThroughput().frames_produced, 0u);
849 TEST_F(FrameSequenceTrackerTest, StateResetDuringSequence) {
850 const char sequence[] = "b(1)B(0,1)n(1)N(1,1)Re(1,0)b(2)n(2)e(2,0)";
851 GenerateSequence(sequence);
852 EXPECT_EQ(ImplThroughput().frames_expected, 0u);
853 EXPECT_EQ(MainThroughput().frames_expected, 0u);
854 EXPECT_EQ(ImplThroughput().frames_produced, 0u);
855 EXPECT_EQ(MainThroughput().frames_produced, 0u);
858 TEST_F(FrameSequenceTrackerTest, NoCompositorDamageSubmitFrame) {
859 const char sequence[] = "b(1)n(1)B(0,1)E(1)s(1)S(1)e(1,1)P(1)b(2)";
860 GenerateSequence(sequence);
861 EXPECT_EQ(ImplThroughput().frames_expected, 2u);
862 EXPECT_EQ(MainThroughput().frames_expected, 1u);
863 EXPECT_EQ(ImplThroughput().frames_produced, 1u);
864 EXPECT_EQ(MainThroughput().frames_produced, 1u);
867 TEST_F(FrameSequenceTrackerTest, SequenceStateResetsDuringFrame) {
868 const char sequence[] = "b(1)Rn(1)e(1,0)";
869 GenerateSequence(sequence);
870 EXPECT_EQ(ImplThroughput().frames_expected, 0u);
871 EXPECT_EQ(MainThroughput().frames_expected, 0u);
872 EXPECT_EQ(ImplThroughput().frames_produced, 0u);
873 EXPECT_EQ(MainThroughput().frames_produced, 0u);
875 GenerateSequence("b(2)s(1)e(2,0)P(1)b(4)");
876 EXPECT_EQ(ImplThroughput().frames_expected, 3u);
877 EXPECT_EQ(MainThroughput().frames_expected, 0u);
878 EXPECT_EQ(ImplThroughput().frames_produced, 1u);
879 EXPECT_EQ(MainThroughput().frames_produced, 0u);
882 TEST_F(FrameSequenceTrackerTest, BeginImplFrameBeforeTerminate) {
883 const char sequence[] = "b(1)s(1)e(1,0)b(4)P(1)";
884 GenerateSequence(sequence);
885 EXPECT_EQ(ImplThroughput().frames_expected, 4u);
886 EXPECT_EQ(ImplThroughput().frames_produced, 1u);
887 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
888 EXPECT_EQ(ImplThroughput().frames_expected, 4u);
889 EXPECT_EQ(ImplThroughput().frames_produced, 1u);
892 // b(2417)B(0,2417)E(2417)n(2417)N(2417,2417)
893 TEST_F(FrameSequenceTrackerTest, SequenceNumberReset) {
894 const char sequence[] =
895 "b(6)B(0,6)n(6)e(6,0)Rb(1)B(0,1)N(1,1)n(1)e(1,0)b(2)B(1,2)n(2)e(2,0)";
896 GenerateSequence(sequence);
897 EXPECT_EQ(ImplThroughput().frames_expected, 0u);
898 EXPECT_EQ(MainThroughput().frames_expected, 1u);
901 TEST_F(FrameSequenceTrackerTest, MainThroughputWithHighLatency) {
902 const char sequence[] = "b(1)B(0,1)n(1)e(1,0)b(2)E(1)s(1)S(1)e(2,1)P(1)";
903 GenerateSequence(sequence);
904 EXPECT_EQ(ImplThroughput().frames_expected, 1u);
905 EXPECT_EQ(ImplThroughput().frames_produced, 1u);
906 EXPECT_EQ(MainThroughput().frames_expected, 2u);
907 EXPECT_EQ(MainThroughput().frames_produced, 1u);
910 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame1) {
911 GenerateSequence("b(1)s(1)e(1,0)b(4)");
912 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
913 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
914 FrameSequenceTracker* removal_tracker =
915 collection_.GetRemovalTrackerForTesting(
916 FrameSequenceTrackerType::kTouchScroll);
917 EXPECT_EQ(GetTerminationStatus(removal_tracker),
918 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
919 GenerateSequence("P(1)");
920 // There is still one impl-frame not processed not, so the tracker is not yet
921 // ready for termination.
922 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
923 EXPECT_EQ(GetTerminationStatus(removal_tracker),
924 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
927 // Following 3 cases are for: b(1)s(1)e(1,0)P(1), and StopSequence can happen
928 // anywhere after b and before P.
929 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame2) {
930 base::HistogramTester histogram_tester;
931 // Ensure we have enough data to report.
932 ImplThroughput().frames_expected = 100u;
933 ImplThroughput().frames_produced = 100u;
935 GenerateSequence("b(1)");
936 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
937 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
938 FrameSequenceTracker* removal_tracker =
939 collection_.GetRemovalTrackerForTesting(
940 FrameSequenceTrackerType::kTouchScroll);
941 EXPECT_EQ(GetTerminationStatus(removal_tracker),
942 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
943 GenerateSequence("s(1)e(1,0)P(1)");
944 // Now the |removal_tracker| should have been destroyed.
945 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
948 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
949 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
952 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame3) {
953 base::HistogramTester histogram_tester;
954 // Ensure we have enough data to report.
955 ImplThroughput().frames_expected = 100u;
956 ImplThroughput().frames_produced = 100u;
958 GenerateSequence("b(1)s(1)");
959 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
960 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
961 FrameSequenceTracker* removal_tracker =
962 collection_.GetRemovalTrackerForTesting(
963 FrameSequenceTrackerType::kTouchScroll);
964 EXPECT_EQ(GetTerminationStatus(removal_tracker),
965 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
966 GenerateSequence("e(1,0)P(1)");
967 // Now the |removal_tracker| should have been destroyed.
968 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
971 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
972 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
975 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame4) {
976 base::HistogramTester histogram_tester;
977 // Ensure we have enough data to report.
978 ImplThroughput().frames_expected = 100u;
979 ImplThroughput().frames_produced = 100u;
981 GenerateSequence("b(1)s(1)e(1,0)");
982 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
983 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
984 FrameSequenceTracker* removal_tracker =
985 collection_.GetRemovalTrackerForTesting(
986 FrameSequenceTrackerType::kTouchScroll);
987 EXPECT_EQ(GetTerminationStatus(removal_tracker),
988 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
989 GenerateSequence("P(1)");
990 // Now the |removal_tracker| should have been destroyed.
991 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
994 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
995 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
998 // Following 2 cases are for: b(1)s(1)P(1), and StopSequence can happen
999 // anywhere after b and before P. Because there is no e when P happens, the
1000 // tracker is not ready for termination.
1001 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame5) {
1002 GenerateSequence("b(1)");
1003 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1004 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1005 FrameSequenceTracker* removal_tracker =
1006 collection_.GetRemovalTrackerForTesting(
1007 FrameSequenceTrackerType::kTouchScroll);
1008 EXPECT_EQ(GetTerminationStatus(removal_tracker),
1009 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1010 GenerateSequence("s(1)P(1)");
1011 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1012 EXPECT_EQ(GetTerminationStatus(removal_tracker),
1013 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1016 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame6) {
1017 GenerateSequence("b(1)s(1)");
1018 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1019 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1020 FrameSequenceTracker* removal_tracker =
1021 collection_.GetRemovalTrackerForTesting(
1022 FrameSequenceTrackerType::kTouchScroll);
1023 EXPECT_EQ(GetTerminationStatus(removal_tracker),
1024 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1025 GenerateSequence("P(1)");
1026 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1027 EXPECT_EQ(GetTerminationStatus(removal_tracker),
1028 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1031 // All the following cases are for one complete impl + one incomplete:
1032 // b(1)s(1)e(1,0)xxxxxxxxP(1)
1033 // The 'xxxxx' is an incomplete impl frame that has no damage, it could be
1034 // 1. b(2)n(2)e(2,0)P(1), and StopSequence can happen anywhere after b and
1036 // 2. b(2)n(2)P(1), and StopSequence can happen anywhere after b and before P.
1037 // In this case, the tracker is not ready for termination yet because e never
1039 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame7) {
1040 base::HistogramTester histogram_tester;
1041 // Ensure we have enough data to report.
1042 ImplThroughput().frames_expected = 100u;
1043 ImplThroughput().frames_produced = 100u;
1045 GenerateSequence("b(1)s(1)e(1,0)b(2)");
1046 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1047 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1048 FrameSequenceTracker* removal_tracker =
1049 collection_.GetRemovalTrackerForTesting(
1050 FrameSequenceTrackerType::kTouchScroll);
1051 EXPECT_EQ(GetTerminationStatus(removal_tracker),
1052 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1053 GenerateSequence("n(2)e(2,0)P(1)");
1054 // Now the |removal_tracker| should have been destroyed.
1055 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
1057 std::string metric =
1058 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
1059 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1062 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame8) {
1063 base::HistogramTester histogram_tester;
1064 // Ensure we have enough data to report.
1065 ImplThroughput().frames_expected = 100u;
1066 ImplThroughput().frames_produced = 100u;
1068 GenerateSequence("b(1)s(1)e(1,0)b(2)n(2)");
1069 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1070 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1071 FrameSequenceTracker* removal_tracker =
1072 collection_.GetRemovalTrackerForTesting(
1073 FrameSequenceTrackerType::kTouchScroll);
1074 EXPECT_EQ(GetTerminationStatus(removal_tracker),
1075 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1076 GenerateSequence("e(2,0)P(1)");
1077 // Now the |removal_tracker| should have been destroyed.
1078 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
1080 std::string metric =
1081 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
1082 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1085 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame9) {
1086 base::HistogramTester histogram_tester;
1087 // Ensure we have enough data to report.
1088 ImplThroughput().frames_expected = 100u;
1089 ImplThroughput().frames_produced = 100u;
1091 GenerateSequence("b(1)s(1)e(1,0)b(2)n(2)e(2,0)");
1092 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1093 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1094 FrameSequenceTracker* removal_tracker =
1095 collection_.GetRemovalTrackerForTesting(
1096 FrameSequenceTrackerType::kTouchScroll);
1097 EXPECT_EQ(GetTerminationStatus(removal_tracker),
1098 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1099 GenerateSequence("P(1)");
1100 // Now the |removal_tracker| should have been destroyed.
1101 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
1103 std::string metric =
1104 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
1105 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1108 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame10) {
1109 GenerateSequence("b(1)s(1)e(1,0)b(2)");
1110 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1111 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1112 FrameSequenceTracker* removal_tracker =
1113 collection_.GetRemovalTrackerForTesting(
1114 FrameSequenceTrackerType::kTouchScroll);
1115 EXPECT_EQ(GetTerminationStatus(removal_tracker),
1116 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1117 GenerateSequence("n(2)P(1)");
1118 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1119 EXPECT_EQ(GetTerminationStatus(removal_tracker),
1120 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1123 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame11) {
1124 GenerateSequence("b(1)s(1)e(1,0)b(2)n(2)");
1125 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1126 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1127 FrameSequenceTracker* removal_tracker =
1128 collection_.GetRemovalTrackerForTesting(
1129 FrameSequenceTrackerType::kTouchScroll);
1130 EXPECT_EQ(GetTerminationStatus(removal_tracker),
1131 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1132 GenerateSequence("P(1)");
1133 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1134 EXPECT_EQ(GetTerminationStatus(removal_tracker),
1135 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1138 // Following tests are for the case where the last impl-frame has no damage.
1139 // Basically b(1)s(1)e(1)P(1)b(2)n(2)e(2). And StopSequence can happen any time
1141 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame12) {
1142 base::HistogramTester histogram_tester;
1143 // Ensure we have enough data to report.
1144 ImplThroughput().frames_expected = 100u;
1145 ImplThroughput().frames_produced = 100u;
1147 GenerateSequence("b(1)s(1)e(1,0)P(1)b(2)");
1148 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1149 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1150 FrameSequenceTracker* removal_tracker =
1151 collection_.GetRemovalTrackerForTesting(
1152 FrameSequenceTrackerType::kTouchScroll);
1153 EXPECT_EQ(GetTerminationStatus(removal_tracker),
1154 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1155 GenerateSequence("n(2)e(2,0)");
1156 // Now the |removal_tracker| should have been destroyed.
1157 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
1159 std::string metric =
1160 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
1161 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1164 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame13) {
1165 base::HistogramTester histogram_tester;
1166 // Ensure we have enough data to report.
1167 ImplThroughput().frames_expected = 100u;
1168 ImplThroughput().frames_produced = 100u;
1170 GenerateSequence("b(1)s(1)e(1,0)P(1)b(2)n(2)");
1171 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1172 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1173 FrameSequenceTracker* removal_tracker =
1174 collection_.GetRemovalTrackerForTesting(
1175 FrameSequenceTrackerType::kTouchScroll);
1176 EXPECT_EQ(GetTerminationStatus(removal_tracker),
1177 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1178 GenerateSequence("e(2,0)");
1179 // Now the |removal_tracker| should have been destroyed.
1180 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
1182 std::string metric =
1183 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
1184 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1187 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame14) {
1188 base::HistogramTester histogram_tester;
1189 // Ensure we have enough data to report.
1190 ImplThroughput().frames_expected = 100u;
1191 ImplThroughput().frames_produced = 100u;
1193 GenerateSequence("b(1)s(1)e(1,0)P(1)b(2)n(2)e(2,0)");
1194 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1195 // The tracker should have been removed from the removal_tracker_ list.
1196 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
1198 std::string metric =
1199 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
1200 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1203 // Following tests are for the case where the presentation of the first impl
1204 // frame arrives late, and a second impl frame has started, and the tracker is
1205 // scheduled to terminate before the second impl frame starts. Basically:
1206 // 1. b(1)s(1)e(1,0)b(2)s(2)e(2,0)P(1), and StopSequence happens anywhere after
1207 // b(1) and before b(2)
1208 // 2. b(1)s(1)e(1,0)b(2)n(2)e(2,0)P(1), and StopSequence happens anywhere after
1209 // b(1) and before b(2)
1210 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame15) {
1211 base::HistogramTester histogram_tester;
1212 // Ensure we have enough data to report.
1213 ImplThroughput().frames_expected = 100u;
1214 ImplThroughput().frames_produced = 100u;
1216 GenerateSequence("b(1)");
1217 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1218 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1219 FrameSequenceTracker* removal_tracker =
1220 collection_.GetRemovalTrackerForTesting(
1221 FrameSequenceTrackerType::kTouchScroll);
1222 EXPECT_EQ(GetTerminationStatus(removal_tracker),
1223 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1224 GenerateSequence("s(1)e(1,0)b(2)s(2)e(2,0)P(1)");
1225 // Now the |removal_tracker| should have been destroyed.
1226 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
1228 std::string metric =
1229 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
1230 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1233 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame16) {
1234 base::HistogramTester histogram_tester;
1235 // Ensure we have enough data to report.
1236 ImplThroughput().frames_expected = 100u;
1237 ImplThroughput().frames_produced = 100u;
1239 GenerateSequence("b(1)s(1)");
1240 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1241 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1242 FrameSequenceTracker* removal_tracker =
1243 collection_.GetRemovalTrackerForTesting(
1244 FrameSequenceTrackerType::kTouchScroll);
1245 EXPECT_EQ(GetTerminationStatus(removal_tracker),
1246 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1247 GenerateSequence("e(1,0)b(2)s(2)e(2,0)P(1)");
1248 // Now the |removal_tracker| should have been destroyed.
1249 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
1251 std::string metric =
1252 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
1253 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1256 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame17) {
1257 base::HistogramTester histogram_tester;
1258 // Ensure we have enough data to report.
1259 ImplThroughput().frames_expected = 100u;
1260 ImplThroughput().frames_produced = 100u;
1262 GenerateSequence("b(1)s(1)e(1,0)");
1263 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1264 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1265 FrameSequenceTracker* removal_tracker =
1266 collection_.GetRemovalTrackerForTesting(
1267 FrameSequenceTrackerType::kTouchScroll);
1268 EXPECT_EQ(GetTerminationStatus(removal_tracker),
1269 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1270 GenerateSequence("b(2)s(2)e(2,0)P(1)");
1271 // Now the |removal_tracker| should have been destroyed.
1272 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
1274 std::string metric =
1275 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
1276 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1279 // The second impl-frame has no damage.
1280 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame18) {
1281 base::HistogramTester histogram_tester;
1282 // Ensure we have enough data to report.
1283 ImplThroughput().frames_expected = 100u;
1284 ImplThroughput().frames_produced = 100u;
1286 GenerateSequence("b(1)");
1287 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1288 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1289 FrameSequenceTracker* removal_tracker =
1290 collection_.GetRemovalTrackerForTesting(
1291 FrameSequenceTrackerType::kTouchScroll);
1292 EXPECT_EQ(GetTerminationStatus(removal_tracker),
1293 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1294 GenerateSequence("s(1)e(1,0)b(2)n(2)e(2,0)P(1)");
1295 // Now the |removal_tracker| should have been destroyed.
1296 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
1298 std::string metric =
1299 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
1300 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1303 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame19) {
1304 base::HistogramTester histogram_tester;
1305 // Ensure we have enough data to report.
1306 ImplThroughput().frames_expected = 100u;
1307 ImplThroughput().frames_produced = 100u;
1309 GenerateSequence("b(1)s(1)");
1310 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1311 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1312 FrameSequenceTracker* removal_tracker =
1313 collection_.GetRemovalTrackerForTesting(
1314 FrameSequenceTrackerType::kTouchScroll);
1315 EXPECT_EQ(GetTerminationStatus(removal_tracker),
1316 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1317 GenerateSequence("e(1,0)b(2)n(2)e(2,0)P(1)");
1318 // Now the |removal_tracker| should have been destroyed.
1319 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
1321 std::string metric =
1322 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
1323 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1326 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame20) {
1327 base::HistogramTester histogram_tester;
1328 // Ensure we have enough data to report.
1329 ImplThroughput().frames_expected = 100u;
1330 ImplThroughput().frames_produced = 100u;
1332 GenerateSequence("b(1)s(1)e(1,0)");
1333 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1334 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1335 FrameSequenceTracker* removal_tracker =
1336 collection_.GetRemovalTrackerForTesting(
1337 FrameSequenceTrackerType::kTouchScroll);
1338 EXPECT_EQ(GetTerminationStatus(removal_tracker),
1339 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1340 GenerateSequence("b(2)n(2)e(2,0)P(1)");
1341 // Now the |removal_tracker| should have been destroyed.
1342 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
1344 std::string metric =
1345 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
1346 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1349 // Following cases test that no frame needs to be presented, basically:
1350 // b(1)n(1)e(1,0), and StopSequence can happen anytime after b(1).
1351 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame21) {
1352 base::HistogramTester histogram_tester;
1353 // Ensure we have enough data to report.
1354 ImplThroughput().frames_expected = 100u;
1355 ImplThroughput().frames_produced = 100u;
1357 GenerateSequence("b(1)");
1358 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1359 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1360 FrameSequenceTracker* removal_tracker =
1361 collection_.GetRemovalTrackerForTesting(
1362 FrameSequenceTrackerType::kTouchScroll);
1363 EXPECT_EQ(GetTerminationStatus(removal_tracker),
1364 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1365 GenerateSequence("n(1)e(1,0)");
1366 // Ensure that this tracker is actually removed from the |removal_trackers_|
1367 // before the test terminates.
1368 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
1370 // If the tracker is terminated successfully, we should see this UMA.
1371 std::string metric =
1372 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
1373 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1376 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame22) {
1377 base::HistogramTester histogram_tester;
1378 // Ensure we have enough data to report.
1379 ImplThroughput().frames_expected = 100u;
1380 ImplThroughput().frames_produced = 100u;
1382 GenerateSequence("b(1)n(1)");
1383 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1384 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1385 FrameSequenceTracker* removal_tracker =
1386 collection_.GetRemovalTrackerForTesting(
1387 FrameSequenceTrackerType::kTouchScroll);
1388 EXPECT_EQ(GetTerminationStatus(removal_tracker),
1389 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1390 GenerateSequence("e(1,0)");
1391 // Ensure that this tracker is actually removed from the |removal_trackers_|
1392 // before the test terminates.
1393 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
1395 // If the tracker is terminated successfully, we should see this UMA.
1396 std::string metric =
1397 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
1398 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1401 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame23) {
1402 base::HistogramTester histogram_tester;
1403 // Ensure we have enough data to report.
1404 ImplThroughput().frames_expected = 100u;
1405 ImplThroughput().frames_produced = 100u;
1407 GenerateSequence("b(1)n(1)e(1,0)");
1408 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1409 // Ensure that this tracker is actually removed from the |removal_trackers_|
1410 // before the test terminates.
1411 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
1413 // If the tracker is terminated successfully, we should see this UMA.
1414 std::string metric =
1415 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
1416 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1419 // This test ensure that the tracker would terminate at e.
1420 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame24) {
1421 GenerateSequence("b(1)s(1)P(1)");
1422 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1423 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1424 GenerateSequence("e(1,0)");
1425 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
1428 TEST_F(FrameSequenceTrackerTest, IgnoredFrameTokensRemovedAtPresentation1) {
1429 GenerateSequence("b(5)s(1)e(5,0)P(1)");
1430 auto args = CreateBeginFrameArgs(/*source_id=*/1u, 1u);
1431 // Ack to an impl frame that doesn't exist in this tracker.
1432 collection_.NotifySubmitFrame(2, /*has_missing_content=*/false,
1433 viz::BeginFrameAck(args, true), args);
1434 EXPECT_EQ(IgnoredFrameTokens().size(), 1u);
1435 GenerateSequence("P(3)");
1436 // Any token that is < 3 should have been removed.
1437 EXPECT_EQ(IgnoredFrameTokens().size(), 0u);
1440 // Test the case where the frame tokens wraps around the 32-bit max value.
1441 TEST_F(FrameSequenceTrackerTest, IgnoredFrameTokensRemovedAtPresentation2) {
1442 GenerateSequence("b(5)");
1443 auto args = CreateBeginFrameArgs(1u, 1u);
1444 // Ack to an impl frame that doesn't exist in this tracker.
1445 collection_.NotifySubmitFrame(UINT32_MAX, /*has_missing_content=*/false,
1446 viz::BeginFrameAck(args, true), args);
1447 EXPECT_EQ(IgnoredFrameTokens().size(), 1u);
1449 args = CreateBeginFrameArgs(1u, 5u);
1450 collection_.NotifySubmitFrame(1, false, viz::BeginFrameAck(args, true), args);
1451 GenerateSequence("e(5,0)P(1)");
1452 EXPECT_TRUE(IgnoredFrameTokens().empty());
1455 TEST_F(FrameSequenceTrackerTest, TerminationWithNullPresentationTimeStamp) {
1456 GenerateSequence("b(1)s(1)");
1457 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1458 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1459 // Even if the presentation timestamp is null, as long as this presentation
1460 // is acking the last impl frame, we consider that impl frame completed and
1461 // so the tracker is ready for termination.
1462 collection_.NotifyFramePresented(
1463 1, {base::TimeTicks(), viz::BeginFrameArgs::DefaultInterval(), 0});
1464 GenerateSequence("e(1,0)");
1465 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
1468 // Test that a tracker is terminated after 3 submitted frames, remove this
1469 // once crbug.com/1072482 is fixed.
1470 TEST_F(FrameSequenceTrackerTest, TerminationAfterThreeSubmissions1) {
1471 GenerateSequence("b(1)s(1)e(1,0)");
1472 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1473 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1474 GenerateSequence("b(2)s(2)e(2,0)b(3)s(3)e(3,0)b(4)s(4)e(4,0)b(5)s(5)e(5,0)");
1475 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
1478 TEST_F(FrameSequenceTrackerTest, TerminationAfterThreeSubmissions2) {
1479 GenerateSequence("b(1)");
1480 auto args = CreateBeginFrameArgs(1u, 1u);
1481 // Ack to an impl frame that doesn't exist in this tracker.
1482 collection_.NotifySubmitFrame(UINT32_MAX, /*has_missing_content=*/false,
1483 viz::BeginFrameAck(args, true), args);
1484 GenerateSequence("e(1,0)");
1485 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1486 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1487 GenerateSequence("b(2)s(1)e(2,0)b(3)s(2)e(3,0)b(4)s(3)e(4,0)");
1488 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
1491 TEST_F(FrameSequenceTrackerTest, TerminationAfterThreeSubmissions3) {
1493 "b(1)s(1)e(1,0)P(1)b(2)s(2)e(2,0)P(2)b(3)s(3)e(3,0)P(3)b(4)");
1494 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1495 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1496 GenerateSequence("s(4)");
1497 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1500 TEST_F(FrameSequenceTrackerTest, OffScreenMainDamage1) {
1501 const char sequence[] =
1502 "b(1)B(0,1)n(1)e(1,0)b(2)E(1)B(1,2)n(2)e(2,1)b(3)E(2)B(2,3)n(3)e(3,2)";
1503 GenerateSequence(sequence);
1504 EXPECT_EQ(ImplThroughput().frames_expected, 0u);
1505 // At E(2), B(0,1) is treated no damage.
1506 EXPECT_EQ(MainThroughput().frames_expected, 2u);
1509 TEST_F(FrameSequenceTrackerTest, OffScreenMainDamage2) {
1510 const char sequence[] =
1511 "b(1)B(0,1)n(1)e(1,0)b(2)E(1)B(1,2)n(2)e(2,1)b(3)n(3)e(3,1)b(4)n(4)e(4,1)"
1514 GenerateSequence(sequence);
1515 EXPECT_EQ(ImplThroughput().frames_expected, 0u);
1516 // At E(2), B(0,1) is treated as no damage.
1517 EXPECT_EQ(MainThroughput().frames_expected, 7u);
1520 TEST_F(FrameSequenceTrackerTest, OffScreenMainDamage3) {
1521 const char sequence[] =
1522 "b(34)B(0,34)n(34)e(34,0)b(35)n(35)e(35,0)b(36)E(34)n(36)e(36,34)b(39)s("
1524 GenerateSequence(sequence);
1525 EXPECT_EQ(ImplThroughput().frames_expected, 1u);
1526 EXPECT_EQ(MainThroughput().frames_expected, 1u);
1529 TEST_F(FrameSequenceTrackerTest, OffScreenMainDamage4) {
1530 const char sequence[] =
1531 "b(9)B(0,9)n(9)Re(9,0)E(9)b(11)B(0,11)n(11)e(11,9)b(12)E(11)B(11,12)s(1)"
1532 "S(11)e(12,11)b(13)E(12)s(2)S(12)";
1533 GenerateSequence(sequence);
1534 EXPECT_EQ(ImplThroughput().frames_expected, 2u);
1535 EXPECT_EQ(MainThroughput().frames_expected, 2u);
1538 TEST_F(FrameSequenceTrackerTest, OffScreenMainDamage5) {
1539 const char sequence[] =
1540 "b(1)B(0,1)E(1)s(1)S(1)e(1,0)b(2)n(2)e(2,0)b(3)B(1,3)n(3)e(3,0)E(3)b(4)B("
1543 GenerateSequence(sequence);
1544 EXPECT_EQ(ImplThroughput().frames_expected, 1u);
1545 // At E(4), we treat B(1,3) as if it had no damage.
1546 EXPECT_EQ(MainThroughput().frames_expected, 3u);
1549 TEST_F(FrameSequenceTrackerTest, OffScreenMainDamage6) {
1550 const char sequence[] =
1551 "b(1)B(0,1)E(1)s(1)S(1)e(1,1)b(2)B(1,2)E(2)n(2)N(2,2)e(2,2)b(3)B(0,3)E(3)"
1554 GenerateSequence(sequence);
1555 EXPECT_EQ(ImplThroughput().frames_expected, 1u);
1556 EXPECT_EQ(MainThroughput().frames_expected, 1u);
1559 TEST_F(FrameSequenceTrackerTest, OffScreenMainDamage7) {
1560 const char sequence[] =
1561 "b(8)B(0,8)n(8)e(8,0)b(9)E(8)B(8,9)E(9)s(1)S(8)e(9,9)b(10)s(2)S(9)e(10,"
1563 GenerateSequence(sequence);
1564 EXPECT_EQ(ImplThroughput().frames_expected, 2u);
1565 EXPECT_EQ(MainThroughput().frames_expected, 1u);
1568 TEST_F(FrameSequenceTrackerTest, OffScreenMainDamage8) {
1569 const char sequence[] =
1570 "b(18)B(0,18)E(18)n(18)N(18,18)Re(18,18)b(20)B(0,20)N(20,20)n(20)N(0,20)"
1572 "20,18)b(21)B(0,21)E(21)s(1)S(21)e(21,21)";
1573 GenerateSequence(sequence);
1574 EXPECT_EQ(ImplThroughput().frames_expected, 1u);
1575 EXPECT_EQ(MainThroughput().frames_expected, 1u);
1578 TEST_F(FrameSequenceTrackerTest, OffScreenMainDamage9) {
1579 const char sequence[] =
1580 "b(78)n(78)Re(78,0)Rb(82)B(0,82)E(82)n(82)N(82,82)Re(82,82)b(86)B(0,86)E("
1582 "86)e(86,86)b(87)s(1)S(86)e(87,86)";
1583 GenerateSequence(sequence);
1584 EXPECT_EQ(ImplThroughput().frames_expected, 1u);
1585 EXPECT_EQ(MainThroughput().frames_expected, 1u);
1588 TEST_F(FrameSequenceTrackerTest, OffScreenMainDamage10) {
1589 const char sequence[] =
1590 "b(2)B(0,2)E(2)n(2)N(2,2)e(2,2)b(3)B(0,3)E(3)n(3)N(3,3)e(3,3)b(4)B(0,4)E("
1592 "4)N(4,4)e(4,4)b(5)B(0,5)E(5)n(5)N(5,5)e(5,5)b(6)B(0,6)n(6)e(6,5)E(6)Rb("
1594 "8)E(8)n(8)N(8,8)e(8,8)";
1595 GenerateSequence(sequence);
1596 EXPECT_EQ(ImplThroughput().frames_expected, 0u);
1597 EXPECT_EQ(MainThroughput().frames_expected, 0u);
1600 // A presentation with a frame token that is > the main frame token submitted.
1601 TEST_F(FrameSequenceTrackerTest, MainThreadPresentWithNonMatchedToken) {
1602 const char sequence[] = "b(1)B(0,1)E(1)s(1)S(1)e(1,0)b(2)s(2)S(1)e(2,1)P(2)";
1603 GenerateSequence(sequence);
1604 EXPECT_EQ(MainThroughput().frames_expected, 1u);
1605 EXPECT_EQ(MainThroughput().frames_produced, 1u);
1608 TEST_F(FrameSequenceTrackerTest, CoalescedMainThreadPresent) {
1609 const char sequence[] =
1610 "b(1)B(0,1)E(1)s(1)S(1)e(1,1)b(2)B(1,2)E(2)s(2)S(2)e(2,2)P(2)";
1611 GenerateSequence(sequence);
1612 EXPECT_EQ(MainThroughput().frames_expected, 2u);
1613 EXPECT_EQ(MainThroughput().frames_produced, 1u);
1616 TEST_F(FrameSequenceTrackerTest, MainThreadPresentWithNullTimeStamp) {
1617 const char sequence[] = "b(1)B(0,1)E(1)s(1)S(1)e(1,1)";
1618 GenerateSequence(sequence);
1619 collection_.NotifyFramePresented(
1620 1, {base::TimeTicks(), viz::BeginFrameArgs::DefaultInterval(),
1621 gfx::PresentationFeedback::kFailure});
1622 EXPECT_EQ(MainThroughput().frames_expected, 1u);
1623 // No presentation, no main frame produced.
1624 EXPECT_EQ(MainThroughput().frames_produced, 0u);
1625 GenerateSequence("b(2)s(2)S(1)e(2,0)P(2)");
1626 EXPECT_EQ(MainThroughput().frames_expected, 1u);
1627 // The main frame update is caught up here.
1628 EXPECT_EQ(MainThroughput().frames_produced, 1u);
1631 TEST_F(FrameSequenceTrackerTest, TrackerTypeEncoding) {
1632 // The test begins with a kTouchScroll tracker
1633 EXPECT_EQ(NumberOfTrackers(), 1u);
1634 ActiveFrameSequenceTrackers active_encoded =
1635 collection_.FrameSequenceTrackerActiveTypes();
1636 EXPECT_EQ(active_encoded, 16); // 1 << 4
1639 TEST_F(FrameSequenceTrackerTest, CustomTrackers) {
1640 CustomTrackerResults results;
1641 collection_.set_custom_tracker_results_added_callback(
1642 base::BindLambdaForTesting([&](const CustomTrackerResults& reported) {
1643 for (const auto& pair : reported)
1644 results[pair.first] = pair.second;
1647 // Start custom tracker 1.
1648 collection_.StartCustomSequence(1);
1649 EXPECT_EQ(1u, NumberOfCustomTrackers());
1652 uint32_t frame_token = 1u;
1653 collection_.NotifyFramePresented(frame_token, {});
1654 EXPECT_EQ(0u, results.size());
1656 // Start custom tracker 2 and 3 in addition to 1.
1657 collection_.StartCustomSequence(2);
1658 collection_.StartCustomSequence(3);
1659 EXPECT_EQ(3u, NumberOfCustomTrackers());
1661 // All custom trackers are running. No reports.
1662 collection_.NotifyFramePresented(frame_token, {});
1663 EXPECT_EQ(0u, results.size());
1665 // Tracker 2 is stopped and scheduled to terminate.
1666 collection_.StopCustomSequence(2);
1667 EXPECT_EQ(2u, NumberOfCustomTrackers());
1669 // Tracker 2 has zero expected frames.
1670 collection_.NotifyFramePresented(frame_token, {});
1671 EXPECT_EQ(1u, results.size());
1672 EXPECT_EQ(0u, results[2].frames_expected);
1674 // Simple sequence of one frame.
1675 const char sequence[] = "b(1)B(0,1)s(1)S(1)e(1,0)P(1)";
1676 GenerateSequence(sequence);
1678 // Stop all custom trackers.
1679 collection_.StopCustomSequence(1);
1680 collection_.StopCustomSequence(3);
1681 EXPECT_EQ(0u, NumberOfCustomTrackers());
1683 // Tracker 1 and 3 and should report.
1684 collection_.NotifyFramePresented(frame_token, {});
1685 EXPECT_EQ(3u, results.size());
1686 EXPECT_EQ(1u, results[1].frames_produced);
1687 EXPECT_EQ(1u, results[1].frames_expected);
1688 EXPECT_EQ(0u, results[2].frames_produced);
1689 EXPECT_EQ(0u, results[2].frames_expected);
1690 EXPECT_EQ(1u, results[3].frames_produced);
1691 EXPECT_EQ(1u, results[3].frames_expected);
1694 TEST_F(FrameSequenceTrackerTest, MergeTrackers) {
1695 // Generate two sequences of scrolls: first with only 1 frame, and then with
1696 // 99 frames. Verify that the two scrolls are merged to report a single
1698 base::HistogramTester histogram_tester;
1699 const char first_sequence[] = "b(1)s(1)e(1,0)P(1)";
1700 GenerateSequence(first_sequence);
1701 EXPECT_EQ(ImplThroughput().frames_expected, 1u);
1702 EXPECT_EQ(ImplThroughput().frames_produced, 1u);
1703 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1705 const char metric[] =
1706 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
1707 histogram_tester.ExpectTotalCount(metric, 0u);
1708 EXPECT_FALSE(TrackerExists(FrameSequenceTrackerType::kTouchScroll));
1711 const char second_sequence[] = "b(2)s(2)e(2,0)P(2)b(100)s(3)e(100,0)P(3)";
1712 GenerateSequence(second_sequence);
1713 EXPECT_EQ(ImplThroughput().frames_expected, 99u);
1714 EXPECT_EQ(ImplThroughput().frames_produced, 2u);
1715 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1716 EXPECT_FALSE(TrackerExists(FrameSequenceTrackerType::kTouchScroll));
1717 histogram_tester.ExpectTotalCount(metric, 1u);
1718 EXPECT_THAT(histogram_tester.GetAllSamples(metric),
1719 testing::ElementsAre(base::Bucket(97, 1)));
1722 TEST_F(FrameSequenceTrackerTest, MergeTrackersPresentAfterStopSequence) {
1723 // Generate two sequences of scrolls: first with only 1 frame, and then with
1724 // 99 frames. Verify that the two scrolls are merged to report a single
1725 // metric. For the second sequence, the last frame is presented after the
1727 base::HistogramTester histogram_tester;
1728 const char first_sequence[] = "b(1)s(1)e(1,0)P(1)";
1729 GenerateSequence(first_sequence);
1730 EXPECT_EQ(ImplThroughput().frames_expected, 1u);
1731 EXPECT_EQ(ImplThroughput().frames_produced, 1u);
1732 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1734 const char metric[] =
1735 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
1736 histogram_tester.ExpectTotalCount(metric, 0u);
1737 EXPECT_FALSE(TrackerExists(FrameSequenceTrackerType::kTouchScroll));
1740 const char second_sequence[] = "b(2)s(2)e(2,0)P(2)b(100)s(3)e(100,0)";
1741 GenerateSequence(second_sequence);
1742 EXPECT_EQ(ImplThroughput().frames_expected, 99u);
1743 EXPECT_EQ(ImplThroughput().frames_produced, 1u);
1744 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1745 GenerateSequence("P(3)");
1746 histogram_tester.ExpectTotalCount(metric, 1u);
1747 EXPECT_THAT(histogram_tester.GetAllSamples(metric),
1748 testing::ElementsAre(base::Bucket(97, 1)));
1751 TEST_F(FrameSequenceTrackerTest, MergeTrackersScrollOnSameThread) {
1752 // Do a short scroll on the compositor thread, then do another short scroll on
1753 // the compositor thread. Make sure these are merged.
1754 base::HistogramTester histogram_tester;
1755 const char first_sequence[] = "b(1)s(1)e(1,0)P(1)b(80)s(2)e(80,0)P(2)";
1756 GenerateSequence(first_sequence);
1757 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1759 CreateNewTracker(FrameInfo::SmoothEffectDrivingThread::kCompositor);
1760 const char second_sequence[] = "b(81)s(3)e(81,0)P(3)b(101)s(4)e(101,0)P(4)";
1761 GenerateSequence(second_sequence);
1762 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1764 const char comp_metric[] =
1765 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
1766 const char main_metric[] =
1767 "Graphics.Smoothness.PercentDroppedFrames.MainThread.TouchScroll";
1768 histogram_tester.ExpectTotalCount(comp_metric, 1u);
1769 histogram_tester.ExpectTotalCount(main_metric, 0u);
1772 TEST_F(FrameSequenceTrackerTest, MergeTrackersScrollOnDifferentThreads) {
1773 // Do a short scroll on the compositor thread, then do another short scroll on
1774 // the main-thread. Make sure these are not merged.
1775 base::HistogramTester histogram_tester;
1776 const char compscroll_sequence[] = "b(1)s(1)e(1,0)P(1)b(80)s(2)e(80,0)P(2)";
1777 GenerateSequence(compscroll_sequence);
1778 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1780 CreateNewTracker(FrameInfo::SmoothEffectDrivingThread::kMain);
1781 const char mainscroll_sequence[] =
1782 "b(81)s(3)e(81,0)P(3)b(101)s(4)e(101,0)P(4)";
1783 GenerateSequence(mainscroll_sequence);
1784 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1786 const char comp_metric[] =
1787 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
1788 const char main_metric[] =
1789 "Graphics.Smoothness.PercentDroppedFrames.MainThread.TouchScroll";
1790 histogram_tester.ExpectTotalCount(comp_metric, 0u);
1791 histogram_tester.ExpectTotalCount(main_metric, 0u);