1 /*
2 * Copyright 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #undef LOG_TAG
18 #define LOG_TAG "TexturePoolTest"
19
20 #include <compositionengine/impl/planner/TexturePool.h>
21 #include <gtest/gtest.h>
22 #include <log/log.h>
23 #include <renderengine/mock/RenderEngine.h>
24
25 namespace android::compositionengine::impl::planner {
26 namespace {
27
28 const ui::Size kDisplaySize(1, 1);
29 const ui::Size kDisplaySizeTwo(2, 2);
30
31 class TestableTexturePool : public TexturePool {
32 public:
TestableTexturePool(renderengine::RenderEngine & renderEngine)33 TestableTexturePool(renderengine::RenderEngine& renderEngine) : TexturePool(renderEngine) {}
34
getMinPoolSize() const35 size_t getMinPoolSize() const { return kMinPoolSize; }
getMaxPoolSize() const36 size_t getMaxPoolSize() const { return kMaxPoolSize; }
getPoolSize() const37 size_t getPoolSize() const { return mPool.size(); }
38 };
39
40 struct TexturePoolTest : public testing::Test {
TexturePoolTestandroid::compositionengine::impl::planner::__anon301f42410111::TexturePoolTest41 TexturePoolTest() {
42 const ::testing::TestInfo* const test_info =
43 ::testing::UnitTest::GetInstance()->current_test_info();
44 ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
45 mTexturePool.setEnabled(true);
46 mTexturePool.setDisplaySize(kDisplaySize);
47 }
48
~TexturePoolTestandroid::compositionengine::impl::planner::__anon301f42410111::TexturePoolTest49 ~TexturePoolTest() {
50 const ::testing::TestInfo* const test_info =
51 ::testing::UnitTest::GetInstance()->current_test_info();
52 ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
53 }
54
55 renderengine::mock::RenderEngine mRenderEngine;
56 TestableTexturePool mTexturePool = TestableTexturePool(mRenderEngine);
57 };
58
TEST_F(TexturePoolTest,preallocatesMinPool)59 TEST_F(TexturePoolTest, preallocatesMinPool) {
60 EXPECT_EQ(mTexturePool.getMinPoolSize(), mTexturePool.getPoolSize());
61 }
62
TEST_F(TexturePoolTest,doesNotAllocateBeyondMinPool)63 TEST_F(TexturePoolTest, doesNotAllocateBeyondMinPool) {
64 for (size_t i = 0; i < mTexturePool.getMinPoolSize() + 1; i++) {
65 auto texture = mTexturePool.borrowTexture();
66 }
67
68 EXPECT_EQ(mTexturePool.getMinPoolSize(), mTexturePool.getPoolSize());
69 }
70
TEST_F(TexturePoolTest,cyclesUpToMaxPoolSize)71 TEST_F(TexturePoolTest, cyclesUpToMaxPoolSize) {
72 std::unordered_set<uint64_t> bufferIds;
73 std::deque<std::shared_ptr<TexturePool::AutoTexture>> textures;
74 for (size_t i = 0; i < mTexturePool.getMaxPoolSize(); i++) {
75 textures.emplace_back(mTexturePool.borrowTexture());
76 bufferIds.insert(textures.back()->get()->getBuffer()->getId());
77 }
78
79 EXPECT_EQ(mTexturePool.getMaxPoolSize(), bufferIds.size());
80
81 for (size_t i = 0; i < 3; i++) {
82 textures.pop_front();
83 textures.emplace_back(mTexturePool.borrowTexture());
84 bufferIds.insert(textures.back()->get()->getBuffer()->getId());
85 }
86
87 EXPECT_EQ(mTexturePool.getMaxPoolSize(), bufferIds.size());
88 }
89
TEST_F(TexturePoolTest,goesPastMaxSizeAndRebounds)90 TEST_F(TexturePoolTest, goesPastMaxSizeAndRebounds) {
91 std::unordered_set<uint64_t> bufferIds;
92 std::vector<std::shared_ptr<TexturePool::AutoTexture>> textures;
93 for (size_t i = 0; i < mTexturePool.getMaxPoolSize() + 2; i++) {
94 textures.emplace_back(mTexturePool.borrowTexture());
95 bufferIds.insert(textures.back()->get()->getBuffer()->getId());
96 }
97
98 EXPECT_EQ(mTexturePool.getMaxPoolSize() + 2, bufferIds.size());
99
100 // Return the textures to the pool.
101 // Now when we cycle through the pool it's again bounded by max textures.
102 textures.clear();
103
104 std::unordered_set<uint64_t> newBufferIds;
105 for (size_t i = 0; i < 2 * mTexturePool.getMaxPoolSize(); i++) {
106 auto texture = mTexturePool.borrowTexture();
107 newBufferIds.insert(texture->get()->getBuffer()->getId());
108 }
109
110 EXPECT_EQ(mTexturePool.getMaxPoolSize(), newBufferIds.size());
111 }
112
TEST_F(TexturePoolTest,reallocatesWhenDisplaySizeChanges)113 TEST_F(TexturePoolTest, reallocatesWhenDisplaySizeChanges) {
114 auto texture = mTexturePool.borrowTexture();
115
116 EXPECT_EQ(kDisplaySize.getWidth(),
117 static_cast<int32_t>(texture->get()->getBuffer()->getWidth()));
118 EXPECT_EQ(kDisplaySize.getHeight(),
119 static_cast<int32_t>(texture->get()->getBuffer()->getHeight()));
120 mTexturePool.setDisplaySize(kDisplaySizeTwo);
121
122 EXPECT_EQ(mTexturePool.getMinPoolSize(), mTexturePool.getPoolSize());
123 texture.reset();
124 // When the texture is returned to the pool, the pool now destroys it.
125 EXPECT_EQ(mTexturePool.getMinPoolSize(), mTexturePool.getPoolSize());
126
127 texture = mTexturePool.borrowTexture();
128 EXPECT_EQ(kDisplaySizeTwo.getWidth(),
129 static_cast<int32_t>(texture->get()->getBuffer()->getWidth()));
130 EXPECT_EQ(kDisplaySizeTwo.getHeight(),
131 static_cast<int32_t>(texture->get()->getBuffer()->getHeight()));
132 }
133
TEST_F(TexturePoolTest,freesBuffersWhenDisabled)134 TEST_F(TexturePoolTest, freesBuffersWhenDisabled) {
135 EXPECT_EQ(mTexturePool.getPoolSize(), mTexturePool.getMinPoolSize());
136
137 std::deque<std::shared_ptr<TexturePool::AutoTexture>> textures;
138 for (size_t i = 0; i < mTexturePool.getMinPoolSize() - 1; i++) {
139 textures.emplace_back(mTexturePool.borrowTexture());
140 }
141
142 EXPECT_EQ(mTexturePool.getPoolSize(), 1u);
143 mTexturePool.setEnabled(false);
144 EXPECT_EQ(mTexturePool.getPoolSize(), 0u);
145
146 textures.clear();
147 EXPECT_EQ(mTexturePool.getPoolSize(), 0u);
148 }
149
TEST_F(TexturePoolTest,doesNotHoldBuffersWhenDisabled)150 TEST_F(TexturePoolTest, doesNotHoldBuffersWhenDisabled) {
151 EXPECT_EQ(mTexturePool.getPoolSize(), mTexturePool.getMinPoolSize());
152 mTexturePool.setEnabled(false);
153 EXPECT_EQ(mTexturePool.getPoolSize(), 0u);
154
155 std::deque<std::shared_ptr<TexturePool::AutoTexture>> textures;
156 for (size_t i = 0; i < mTexturePool.getMinPoolSize() - 1; i++) {
157 textures.emplace_back(mTexturePool.borrowTexture());
158 }
159
160 EXPECT_EQ(mTexturePool.getPoolSize(), 0u);
161 textures.clear();
162 EXPECT_EQ(mTexturePool.getPoolSize(), 0u);
163 }
164
TEST_F(TexturePoolTest,reallocatesWhenReEnabled)165 TEST_F(TexturePoolTest, reallocatesWhenReEnabled) {
166 EXPECT_EQ(mTexturePool.getPoolSize(), mTexturePool.getMinPoolSize());
167 mTexturePool.setEnabled(false);
168 EXPECT_EQ(mTexturePool.getPoolSize(), 0u);
169 mTexturePool.setEnabled(true);
170 EXPECT_EQ(mTexturePool.getPoolSize(), mTexturePool.getMinPoolSize());
171 }
172
173 } // namespace
174 } // namespace android::compositionengine::impl::planner
175