OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2013 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 | |
5 #include "content/browser/renderer_host/software_frame_manager.h" | |
6 | |
7 #include <vector> | |
8 | |
9 #include "base/sys_info.h" | |
10 #include "testing/gtest/include/gtest/gtest.h" | |
11 | |
12 namespace { | |
13 | |
14 size_t MaxNumberOfSavedFrames() { | |
15 static size_t max_number_of_saved_frames = std::min( | |
16 5, 2 + (base::SysInfo::AmountOfPhysicalMemoryMB() / 256)); | |
17 return max_number_of_saved_frames; | |
18 } | |
piman
2013/10/23 23:41:40
Ok, so, rather than duplicate the logic, which is
ccameron
2013/10/24 17:56:41
I'd duplicated this in preference to putting Softw
| |
19 | |
20 } // namespace | |
21 | |
22 namespace content { | |
23 | |
24 class FakeSoftwareFrameManagerClient : public SoftwareFrameManagerClient { | |
25 public: | |
26 FakeSoftwareFrameManagerClient() | |
27 : evicted_count_(0), weak_ptr_factory_(this) { | |
28 software_frame_manager_.reset(new SoftwareFrameManager( | |
29 weak_ptr_factory_.GetWeakPtr())); | |
30 } | |
31 virtual ~FakeSoftwareFrameManagerClient() {} | |
32 virtual void SoftwareFrameWasFreed( | |
33 uint32 output_surface_id, unsigned frame_id) OVERRIDE { | |
34 freed_frames_.push_back(std::make_pair(output_surface_id, frame_id)); | |
35 } | |
36 virtual void ReleaseReferencesToSoftwareFrame() OVERRIDE { | |
37 ++evicted_count_; | |
38 } | |
39 | |
40 bool SwapToNewFrame(uint32 output_surface, unsigned frame_id) { | |
41 cc::SoftwareFrameData frame; | |
42 frame.id = frame_id; | |
43 frame.size = gfx::Size(1, 1); | |
44 frame.damage_rect = gfx::Rect(frame.size); | |
45 frame.handle = base::SharedMemory::NULLHandle(); | |
46 return software_frame_manager_->SwapToNewFrame( | |
47 output_surface, &frame, 1.0, base::GetCurrentProcessHandle()); | |
48 } | |
49 | |
50 std::vector<std::pair<uint32,unsigned> > freed_frames_; | |
piman
2013/10/23 23:41:40
nit: private + accessors
ccameron
2013/10/24 17:56:41
Done.
| |
51 size_t evicted_count_; | |
52 | |
53 scoped_ptr<SoftwareFrameManager> software_frame_manager_; | |
54 base::WeakPtrFactory<FakeSoftwareFrameManagerClient> | |
55 weak_ptr_factory_; | |
piman
2013/10/23 23:41:40
nit: DISALLOW_COPY_AND_ASSIGN
ccameron
2013/10/24 17:56:41
Done.
| |
56 }; | |
57 | |
58 class SoftwareFrameManagerTest : public testing::Test { | |
59 public: | |
60 void AllocateClients(size_t num_clients) { | |
61 for (size_t i = 0; i < num_clients; ++i) | |
62 clients_.push_back(new FakeSoftwareFrameManagerClient); | |
63 } | |
64 void FreeClients() { | |
65 for (size_t i = 0; i < clients_.size(); ++i) | |
66 delete clients_[i]; | |
67 clients_.clear(); | |
68 } | |
69 | |
70 std::vector<FakeSoftwareFrameManagerClient*> clients_; | |
piman
2013/10/23 23:41:40
nit: private+accessors, DISALLOW_COPY_AND_ASSIGN
ccameron
2013/10/24 17:56:41
Made this protected instead (since all tests acces
| |
71 }; | |
72 | |
73 TEST_F(SoftwareFrameManagerTest, DoNotEvictVisible) { | |
74 // Create twice as many frames as are allowed. | |
75 AllocateClients(2 * MaxNumberOfSavedFrames()); | |
76 | |
77 // Swap a visible frame to all clients_. Because they are all visible, | |
78 // the should not be evicted. | |
79 for (size_t i = 0; i < clients_.size(); ++i) { | |
80 bool swap_result = clients_[i]->SwapToNewFrame( | |
81 static_cast<uint32>(i), 0); | |
82 clients_[i]->software_frame_manager_->SwapToNewFrameComplete(true); | |
83 EXPECT_TRUE(swap_result); | |
84 EXPECT_EQ(0u, clients_[i]->evicted_count_); | |
85 EXPECT_EQ(0u, clients_[i]->freed_frames_.size()); | |
86 } | |
87 for (size_t i = 0; i < clients_.size(); ++i) { | |
88 EXPECT_EQ(0u, clients_[i]->evicted_count_); | |
89 EXPECT_EQ(0u, clients_[i]->freed_frames_.size()); | |
90 } | |
91 | |
92 // Swap another frame and make sure the original was freed (but not evicted). | |
93 for (size_t i = 0; i < clients_.size(); ++i) { | |
94 bool swap_result = clients_[i]->SwapToNewFrame( | |
95 static_cast<uint32>(i), 1); | |
96 clients_[i]->software_frame_manager_->SwapToNewFrameComplete(true); | |
97 EXPECT_TRUE(swap_result); | |
98 EXPECT_EQ(0u, clients_[i]->evicted_count_); | |
99 EXPECT_EQ(1u, clients_[i]->freed_frames_.size()); | |
100 } | |
101 for (size_t i = 0; i < clients_.size(); ++i) { | |
102 EXPECT_EQ(0u, clients_[i]->evicted_count_); | |
103 EXPECT_EQ(1u, clients_[i]->freed_frames_.size()); | |
104 } | |
105 | |
106 // Mark the frames as nonvisible and make sure they start getting evicted. | |
107 for (size_t i = 0; i < clients_.size(); ++i) { | |
108 clients_[i]->software_frame_manager_->SetVisibility(false); | |
109 if (clients_.size() - i > MaxNumberOfSavedFrames()) { | |
110 EXPECT_EQ(1u, clients_[i]->evicted_count_); | |
111 EXPECT_EQ(2u, clients_[i]->freed_frames_.size()); | |
112 } else { | |
113 EXPECT_EQ(0u, clients_[i]->evicted_count_); | |
114 EXPECT_EQ(1u, clients_[i]->freed_frames_.size()); | |
115 } | |
116 } | |
117 | |
118 // Clean up. | |
119 FreeClients(); | |
120 } | |
121 | |
122 TEST_F(SoftwareFrameManagerTest, DoNotEvictDuringSwap) { | |
123 // Create twice as many frames as are allowed. | |
124 AllocateClients(2 * MaxNumberOfSavedFrames()); | |
125 | |
126 // Swap a visible frame to all clients_. Because they are all visible, | |
127 // the should not be evicted. | |
128 for (size_t i = 0; i < clients_.size(); ++i) { | |
129 bool swap_result = clients_[i]->SwapToNewFrame(static_cast<uint32>(i), 0); | |
130 clients_[i]->software_frame_manager_->SwapToNewFrameComplete(true); | |
131 EXPECT_TRUE(swap_result); | |
132 EXPECT_EQ(0u, clients_[i]->evicted_count_); | |
133 EXPECT_EQ(0u, clients_[i]->freed_frames_.size()); | |
134 } | |
135 for (size_t i = 0; i < clients_.size(); ++i) { | |
136 EXPECT_EQ(0u, clients_[i]->evicted_count_); | |
137 EXPECT_EQ(0u, clients_[i]->freed_frames_.size()); | |
138 } | |
139 | |
140 // Now create a test non-visible client, and swap a non-visible frame in. | |
141 scoped_ptr<FakeSoftwareFrameManagerClient> test_client( | |
142 new FakeSoftwareFrameManagerClient); | |
143 test_client->software_frame_manager_->SetVisibility(false); | |
144 { | |
145 bool swap_result = test_client->SwapToNewFrame( | |
146 static_cast<uint32>(500), 0); | |
147 EXPECT_TRUE(swap_result); | |
148 EXPECT_EQ(0u, test_client->evicted_count_); | |
149 EXPECT_EQ(0u, test_client->freed_frames_.size()); | |
150 test_client->software_frame_manager_->SwapToNewFrameComplete(false); | |
151 EXPECT_EQ(1u, test_client->evicted_count_); | |
152 EXPECT_EQ(1u, test_client->freed_frames_.size()); | |
153 } | |
154 | |
155 // Clean up. | |
156 FreeClients(); | |
157 } | |
158 | |
159 TEST_F(SoftwareFrameManagerTest, Cleanup) { | |
160 // Create twice as many frames as are allowed. | |
161 AllocateClients(2 * MaxNumberOfSavedFrames()); | |
162 | |
163 // Swap a visible frame to all clients_. Because they are all visible, | |
164 // the should not be evicted. | |
165 for (size_t i = 0; i < clients_.size(); ++i) { | |
166 bool swap_result = clients_[i]->SwapToNewFrame(static_cast<uint32>(i), 0); | |
167 clients_[i]->software_frame_manager_->SwapToNewFrameComplete(true); | |
168 EXPECT_TRUE(swap_result); | |
169 EXPECT_EQ(0u, clients_[i]->evicted_count_); | |
170 EXPECT_EQ(0u, clients_[i]->freed_frames_.size()); | |
171 } | |
172 | |
173 // Destroy them. | |
174 FreeClients(); | |
175 | |
176 // Create the maximum number of frames, all non-visible. They should not | |
177 // be evicted, because the previous frames were cleaned up at destruction. | |
178 AllocateClients(MaxNumberOfSavedFrames()); | |
179 for (size_t i = 0; i < clients_.size(); ++i) { | |
180 cc::SoftwareFrameData frame; | |
181 bool swap_result = clients_[i]->SwapToNewFrame(static_cast<uint32>(i), 0); | |
182 clients_[i]->software_frame_manager_->SwapToNewFrameComplete(true); | |
183 EXPECT_TRUE(swap_result); | |
184 EXPECT_EQ(0u, clients_[i]->evicted_count_); | |
185 EXPECT_EQ(0u, clients_[i]->freed_frames_.size()); | |
186 } | |
187 for (size_t i = 0; i < clients_.size(); ++i) { | |
188 EXPECT_EQ(0u, clients_[i]->evicted_count_); | |
189 EXPECT_EQ(0u, clients_[i]->freed_frames_.size()); | |
190 } | |
191 | |
192 // Clean up. | |
193 FreeClients(); | |
194 } | |
195 | |
196 TEST_F(SoftwareFrameManagerTest, EvictVersusFree) { | |
197 // Create twice as many frames as are allowed and swap a visible frame to all | |
198 // clients_. Because they are all visible, the should not be evicted. | |
199 AllocateClients(2 * MaxNumberOfSavedFrames()); | |
200 for (size_t i = 0; i < clients_.size(); ++i) { | |
201 clients_[i]->SwapToNewFrame(static_cast<uint32>(i), 0); | |
202 clients_[i]->software_frame_manager_->SwapToNewFrameComplete(true); | |
203 } | |
204 | |
205 // Create a test client with a frame that is not evicted. | |
206 scoped_ptr<FakeSoftwareFrameManagerClient> test_client( | |
207 new FakeSoftwareFrameManagerClient); | |
208 bool swap_result = test_client->SwapToNewFrame(static_cast<uint32>(500), 0); | |
209 EXPECT_TRUE(swap_result); | |
210 test_client->software_frame_manager_->SwapToNewFrameComplete(true); | |
211 EXPECT_EQ(0u, test_client->evicted_count_); | |
212 EXPECT_EQ(0u, test_client->freed_frames_.size()); | |
213 | |
214 // Take out a reference on the current frame and make the memory manager | |
215 // evict it. The frame will not be freed until this reference is released. | |
216 cc::TextureMailbox mailbox; | |
217 scoped_ptr<cc::SingleReleaseCallback> callback; | |
218 test_client->software_frame_manager_->GetCurrentFrameMailbox( | |
219 &mailbox, &callback); | |
220 test_client->software_frame_manager_->SetVisibility(false); | |
221 EXPECT_EQ(1u, test_client->evicted_count_); | |
222 EXPECT_EQ(0u, test_client->freed_frames_.size()); | |
223 | |
224 // Swap a few frames. The frames will be freed as they are swapped out. | |
225 for (size_t frame = 0; frame < 10; ++frame) { | |
226 bool swap_result = test_client->SwapToNewFrame( | |
227 static_cast<uint32>(500), 1 + static_cast<int>(frame)); | |
228 EXPECT_TRUE(swap_result); | |
229 test_client->software_frame_manager_->SwapToNewFrameComplete(true); | |
230 EXPECT_EQ(frame, test_client->freed_frames_.size()); | |
231 EXPECT_EQ(1u, test_client->evicted_count_); | |
232 } | |
233 | |
234 // The reference to the frame that we didn't free is in the callback | |
235 // object. It will go away when the callback is destroyed. | |
236 EXPECT_EQ(9u, test_client->freed_frames_.size()); | |
237 EXPECT_EQ(1u, test_client->evicted_count_); | |
238 callback->Run(0, false); | |
239 callback.reset(); | |
240 EXPECT_EQ(10u, test_client->freed_frames_.size()); | |
241 EXPECT_EQ(1u, test_client->evicted_count_); | |
242 | |
243 FreeClients(); | |
244 } | |
245 | |
246 } // namespace content | |
OLD | NEW |