| // Copyright 2019 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "cc/metrics/frame_sequence_tracker.h" |
| |
| #include "base/macros.h" |
| #include "cc/metrics/compositor_frame_reporting_controller.h" |
| #include "components/viz/common/frame_sinks/begin_frame_args.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace cc { |
| namespace { |
| |
| class FrameSequenceTrackerTest; |
| |
| class FrameSequenceTrackerTest : public testing::Test { |
| public: |
| const uint32_t kImplDamage = 0x1; |
| const uint32_t kMainDamage = 0x2; |
| |
| FrameSequenceTrackerTest() |
| : compositor_frame_reporting_controller_( |
| std::make_unique<CompositorFrameReportingController>()), |
| collection_(compositor_frame_reporting_controller_.get()), |
| tracker_( |
| collection_.CreateTracker(FrameSequenceTrackerType::kTouchScroll)) { |
| } |
| ~FrameSequenceTrackerTest() override = default; |
| |
| std::unique_ptr<FrameSequenceTracker> CreateNewTracker() { |
| return collection_.CreateTracker(FrameSequenceTrackerType::kTouchScroll); |
| } |
| |
| viz::BeginFrameArgs CreateBeginFrameArgs(uint64_t source_id, |
| uint64_t sequence_number) { |
| auto now = base::TimeTicks::Now(); |
| auto interval = base::TimeDelta::FromMilliseconds(16); |
| auto deadline = now + interval; |
| return viz::BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, source_id, |
| sequence_number, now, deadline, interval, |
| viz::BeginFrameArgs::NORMAL); |
| } |
| |
| void StartImplAndMainFrames(const viz::BeginFrameArgs& args) { |
| collection_.NotifyBeginImplFrame(args); |
| collection_.NotifyBeginMainFrame(args); |
| } |
| |
| uint32_t DispatchCompleteFrame(const viz::BeginFrameArgs& args, |
| uint32_t damage_type) { |
| StartImplAndMainFrames(args); |
| |
| if (damage_type & kImplDamage) { |
| if (!(damage_type & kMainDamage)) { |
| collection_.NotifyMainFrameCausedNoDamage(args); |
| } |
| uint32_t frame_token = NextFrameToken(); |
| collection_.NotifySubmitFrame(frame_token, viz::BeginFrameAck(args, true), |
| args); |
| return frame_token; |
| } else { |
| collection_.NotifyImplFrameCausedNoDamage( |
| viz::BeginFrameAck(args, false)); |
| collection_.NotifyMainFrameCausedNoDamage(args); |
| } |
| return 0; |
| } |
| |
| uint32_t NextFrameToken() { |
| static uint32_t frame_token = 0; |
| return ++frame_token; |
| } |
| |
| protected: |
| std::unique_ptr<CompositorFrameReportingController> |
| compositor_frame_reporting_controller_; |
| FrameSequenceTrackerCollection collection_; |
| std::unique_ptr<FrameSequenceTracker> tracker_; |
| }; |
| |
| // Tests that the tracker works correctly when the source-id for the |
| // begin-frames change. |
| TEST_F(FrameSequenceTrackerTest, SourceIdChangeDuringSequence) { |
| const uint64_t source_1 = 1; |
| uint64_t sequence_1 = 0; |
| |
| // Dispatch some frames, both causing damage to impl/main, and both impl and |
| // main providing damage to the frame. |
| auto args_1 = CreateBeginFrameArgs(source_1, ++sequence_1); |
| DispatchCompleteFrame(args_1, kImplDamage | kMainDamage); |
| args_1 = CreateBeginFrameArgs(source_1, ++sequence_1); |
| DispatchCompleteFrame(args_1, kImplDamage | kMainDamage); |
| |
| // Start a new tracker. |
| auto tracker = CreateNewTracker(); |
| |
| // Change the source-id, and start an impl frame. This time, the main-frame |
| // does not provide any damage. |
| const uint64_t source_2 = 2; |
| uint64_t sequence_2 = 0; |
| auto args_2 = CreateBeginFrameArgs(source_2, ++sequence_2); |
| collection_.NotifyBeginImplFrame(args_2); |
| collection_.NotifyBeginMainFrame(args_2); |
| collection_.NotifyMainFrameCausedNoDamage(args_2); |
| // Since the main-frame did not have any new damage from the latest |
| // BeginFrameArgs, the submit-frame will carry the previous BeginFrameArgs |
| // (from source_1); |
| collection_.NotifySubmitFrame(NextFrameToken(), |
| viz::BeginFrameAck(args_2, true), args_1); |
| } |
| |
| } // namespace |
| } // namespace cc |