blob: 92ba61816c49f5e25561a0c563e800a2a57ce6ba [file] [log] [blame]
Avi Drissman8ba1bad2022-09-13 19:22:361// Copyright 2019 The Chromium Authors
Xiyuan Xiad7e4d942019-06-12 22:32:522// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "components/viz/client/frame_eviction_manager.h"
6
Peter Kastingccea09832025-01-27 18:38:227#include <algorithm>
Xiyuan Xiad7e4d942019-06-12 22:32:528#include <vector>
9
Benoit Lize6325f042022-09-12 10:11:3510#include "base/memory/memory_pressure_listener.h"
Ho Cheungc4c27d8d2023-05-24 14:12:3911#include "base/memory/raw_ptr.h"
Benoit Lize6325f042022-09-12 10:11:3512#include "base/test/test_mock_time_task_runner.h"
Xiyuan Xiad7e4d942019-06-12 22:32:5213#include "testing/gtest/include/gtest/gtest.h"
14
15namespace viz {
16
17namespace {
18
19class TestFrameEvictionManagerClient : public FrameEvictionManagerClient {
20 public:
21 TestFrameEvictionManagerClient() = default;
Benoit Lize6325f042022-09-12 10:11:3522 explicit TestFrameEvictionManagerClient(FrameEvictionManager* manager)
23 : manager_(manager) {}
Peter Boström09c01822021-09-20 22:43:2724
25 TestFrameEvictionManagerClient(const TestFrameEvictionManagerClient&) =
26 delete;
27 TestFrameEvictionManagerClient& operator=(
28 const TestFrameEvictionManagerClient&) = delete;
29
Benoit Lize6325f042022-09-12 10:11:3530 ~TestFrameEvictionManagerClient() override {
31 if (has_frame_)
32 manager_->RemoveFrame(this);
33 }
Xiyuan Xiad7e4d942019-06-12 22:32:5234
35 // FrameEvictionManagerClient:
36 void EvictCurrentFrame() override {
Benoit Lize6325f042022-09-12 10:11:3537 manager_->RemoveFrame(this);
Xiyuan Xiad7e4d942019-06-12 22:32:5238 has_frame_ = false;
39 }
40
41 bool has_frame() const { return has_frame_; }
42
43 private:
Ho Cheungc4c27d8d2023-05-24 14:12:3944 raw_ptr<FrameEvictionManager> manager_ = FrameEvictionManager::GetInstance();
Xiyuan Xiad7e4d942019-06-12 22:32:5245 bool has_frame_ = true;
Xiyuan Xiad7e4d942019-06-12 22:32:5246};
47
48} // namespace
49
Benoit Lize6325f042022-09-12 10:11:3550class FrameEvictionManagerTest : public testing::Test {};
Xiyuan Xiad7e4d942019-06-12 22:32:5251
52TEST_F(FrameEvictionManagerTest, ScopedPause) {
53 constexpr int kMaxSavedFrames = 1;
54 constexpr int kFrames = 2;
55
56 FrameEvictionManager* manager = FrameEvictionManager::GetInstance();
57 manager->set_max_number_of_saved_frames(kMaxSavedFrames);
58
59 std::vector<TestFrameEvictionManagerClient> frames(kFrames);
60 {
61 FrameEvictionManager::ScopedPause scoped_pause;
62
63 for (auto& frame : frames)
64 manager->AddFrame(&frame, /*locked=*/false);
65
66 // All frames stays because |scoped_pause| holds off frame eviction.
Peter Kastingccea09832025-01-27 18:38:2267 EXPECT_EQ(kFrames, std::ranges::count_if(
Peter Kastingc6c2d0a2022-10-19 08:45:3568 frames, &TestFrameEvictionManagerClient::has_frame));
Xiyuan Xiad7e4d942019-06-12 22:32:5269 }
70
71 // Frame eviction happens when |scoped_pause| goes out of scope.
72 EXPECT_EQ(kMaxSavedFrames,
Peter Kastingccea09832025-01-27 18:38:2273 std::ranges::count_if(frames,
74 &TestFrameEvictionManagerClient::has_frame));
Xiyuan Xiad7e4d942019-06-12 22:32:5275}
76
Benoit Lize6325f042022-09-12 10:11:3577TEST_F(FrameEvictionManagerTest, PeriodicCulling) {
Benoit Lize6325f042022-09-12 10:11:3578 // Cannot use a TaskEnvironment as there is already one which is not using
79 // MOCK_TIME.
80 auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>();
81 FrameEvictionManager manager;
82 manager.set_max_number_of_saved_frames(5);
83 manager.SetOverridesForTesting(task_runner, task_runner->GetMockTickClock());
84
85 TestFrameEvictionManagerClient frame1{&manager}, frame2{&manager},
86 frame3{&manager};
87 manager.AddFrame(&frame1, false);
88 task_runner->FastForwardBy(FrameEvictionManager::kPeriodicCullingDelay / 10);
89 manager.AddFrame(&frame2, true);
90 manager.AddFrame(&frame3, false);
91
92 task_runner->FastForwardBy(FrameEvictionManager::kPeriodicCullingDelay);
93 EXPECT_FALSE(frame1.has_frame());
94 EXPECT_TRUE(frame2.has_frame());
95 EXPECT_TRUE(frame3.has_frame()); // Too early for this one.
96 task_runner->FastForwardBy(FrameEvictionManager::kPeriodicCullingDelay);
97 EXPECT_FALSE(frame3.has_frame());
98
99 task_runner->FastForwardBy(FrameEvictionManager::kPeriodicCullingDelay / 2);
100 manager.UnlockFrame(&frame2);
101 EXPECT_TRUE(frame2.has_frame());
102
103 // Pause prevents eviction, but not rescheduling the task. Not using
104 // ScopedPause because it impacts the singleton.
105 manager.Pause();