1 // Copyright 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.
5 #include "content/browser/renderer_host/software_frame_manager.h"
9 #include "base/sys_info.h"
10 #include "testing/gtest/include/gtest/gtest.h"
14 class FakeSoftwareFrameManagerClient
: public SoftwareFrameManagerClient
{
16 FakeSoftwareFrameManagerClient()
17 : evicted_count_(0), weak_ptr_factory_(this) {
18 software_frame_manager_
.reset(new SoftwareFrameManager(
19 weak_ptr_factory_
.GetWeakPtr()));
21 virtual ~FakeSoftwareFrameManagerClient() {}
22 virtual void SoftwareFrameWasFreed(
23 uint32 output_surface_id
, unsigned frame_id
) OVERRIDE
{
24 freed_frames_
.push_back(std::make_pair(output_surface_id
, frame_id
));
26 virtual void ReleaseReferencesToSoftwareFrame() OVERRIDE
{
30 bool SwapToNewFrame(uint32 output_surface
, unsigned frame_id
) {
31 cc::SoftwareFrameData frame
;
33 frame
.size
= gfx::Size(1, 1);
34 frame
.damage_rect
= gfx::Rect(frame
.size
);
35 frame
.handle
= base::SharedMemory::NULLHandle();
36 return software_frame_manager_
->SwapToNewFrame(
37 output_surface
, &frame
, 1.0, base::GetCurrentProcessHandle());
40 SoftwareFrameManager
* software_frame_manager() {
41 return software_frame_manager_
.get();
43 size_t freed_frame_count() const { return freed_frames_
.size(); }
44 size_t evicted_frame_count() const { return evicted_count_
; }
47 std::vector
<std::pair
<uint32
,unsigned> > freed_frames_
;
48 size_t evicted_count_
;
50 scoped_ptr
<SoftwareFrameManager
> software_frame_manager_
;
51 base::WeakPtrFactory
<FakeSoftwareFrameManagerClient
>
54 DISALLOW_COPY_AND_ASSIGN(FakeSoftwareFrameManagerClient
);
57 class SoftwareFrameManagerTest
: public testing::Test
{
59 SoftwareFrameManagerTest() {}
60 void AllocateClients(size_t num_clients
) {
61 for (size_t i
= 0; i
< num_clients
; ++i
)
62 clients_
.push_back(new FakeSoftwareFrameManagerClient
);
65 for (size_t i
= 0; i
< clients_
.size(); ++i
)
69 size_t MaxNumberOfSavedFrames() const {
71 RendererFrameManager::GetInstance()->max_number_of_saved_frames();
76 std::vector
<FakeSoftwareFrameManagerClient
*> clients_
;
79 DISALLOW_COPY_AND_ASSIGN(SoftwareFrameManagerTest
);
82 TEST_F(SoftwareFrameManagerTest
, DoNotEvictVisible
) {
83 // Create twice as many frames as are allowed.
84 AllocateClients(2 * MaxNumberOfSavedFrames());
86 // Swap a visible frame to all clients_. Because they are all visible,
87 // the should not be evicted.
88 for (size_t i
= 0; i
< clients_
.size(); ++i
) {
89 bool swap_result
= clients_
[i
]->SwapToNewFrame(
90 static_cast<uint32
>(i
), 0);
91 clients_
[i
]->software_frame_manager()->SwapToNewFrameComplete(true);
92 EXPECT_TRUE(swap_result
);
93 EXPECT_EQ(0u, clients_
[i
]->evicted_frame_count());
94 EXPECT_EQ(0u, clients_
[i
]->freed_frame_count());
96 for (size_t i
= 0; i
< clients_
.size(); ++i
) {
97 EXPECT_EQ(0u, clients_
[i
]->evicted_frame_count());
98 EXPECT_EQ(0u, clients_
[i
]->freed_frame_count());
101 // Swap another frame and make sure the original was freed (but not evicted).
102 for (size_t i
= 0; i
< clients_
.size(); ++i
) {
103 bool swap_result
= clients_
[i
]->SwapToNewFrame(
104 static_cast<uint32
>(i
), 1);
105 clients_
[i
]->software_frame_manager()->SwapToNewFrameComplete(true);
106 EXPECT_TRUE(swap_result
);
107 EXPECT_EQ(0u, clients_
[i
]->evicted_frame_count());
108 EXPECT_EQ(1u, clients_
[i
]->freed_frame_count());
110 for (size_t i
= 0; i
< clients_
.size(); ++i
) {
111 EXPECT_EQ(0u, clients_
[i
]->evicted_frame_count());
112 EXPECT_EQ(1u, clients_
[i
]->freed_frame_count());
115 // Mark the frames as nonvisible and make sure they start getting evicted.
116 for (size_t i
= 0; i
< clients_
.size(); ++i
) {
117 clients_
[i
]->software_frame_manager()->SetVisibility(false);
118 if (clients_
.size() - i
> MaxNumberOfSavedFrames()) {
119 EXPECT_EQ(1u, clients_
[i
]->evicted_frame_count());
120 EXPECT_EQ(2u, clients_
[i
]->freed_frame_count());
122 EXPECT_EQ(0u, clients_
[i
]->evicted_frame_count());
123 EXPECT_EQ(1u, clients_
[i
]->freed_frame_count());
131 TEST_F(SoftwareFrameManagerTest
, DoNotEvictDuringSwap
) {
132 // Create twice as many frames as are allowed.
133 AllocateClients(2 * MaxNumberOfSavedFrames());
135 // Swap a visible frame to all clients_. Because they are all visible,
136 // the should not be evicted.
137 for (size_t i
= 0; i
< clients_
.size(); ++i
) {
138 bool swap_result
= clients_
[i
]->SwapToNewFrame(static_cast<uint32
>(i
), 0);
139 clients_
[i
]->software_frame_manager()->SwapToNewFrameComplete(true);
140 EXPECT_TRUE(swap_result
);
141 EXPECT_EQ(0u, clients_
[i
]->evicted_frame_count());
142 EXPECT_EQ(0u, clients_
[i
]->freed_frame_count());
144 for (size_t i
= 0; i
< clients_
.size(); ++i
) {
145 EXPECT_EQ(0u, clients_
[i
]->evicted_frame_count());
146 EXPECT_EQ(0u, clients_
[i
]->freed_frame_count());
149 // Now create a test non-visible client, and swap a non-visible frame in.
150 scoped_ptr
<FakeSoftwareFrameManagerClient
> test_client(
151 new FakeSoftwareFrameManagerClient
);
152 test_client
->software_frame_manager()->SetVisibility(false);
154 bool swap_result
= test_client
->SwapToNewFrame(
155 static_cast<uint32
>(500), 0);
156 EXPECT_TRUE(swap_result
);
157 EXPECT_EQ(0u, test_client
->evicted_frame_count());
158 EXPECT_EQ(0u, test_client
->freed_frame_count());
159 test_client
->software_frame_manager()->SwapToNewFrameComplete(false);
160 EXPECT_EQ(1u, test_client
->evicted_frame_count());
161 EXPECT_EQ(1u, test_client
->freed_frame_count());
168 TEST_F(SoftwareFrameManagerTest
, Cleanup
) {
169 // Create twice as many frames as are allowed.
170 AllocateClients(2 * MaxNumberOfSavedFrames());
172 // Swap a visible frame to all clients_. Because they are all visible,
173 // the should not be evicted.
174 for (size_t i
= 0; i
< clients_
.size(); ++i
) {
175 bool swap_result
= clients_
[i
]->SwapToNewFrame(static_cast<uint32
>(i
), 0);
176 clients_
[i
]->software_frame_manager()->SwapToNewFrameComplete(true);
177 EXPECT_TRUE(swap_result
);
178 EXPECT_EQ(0u, clients_
[i
]->evicted_frame_count());
179 EXPECT_EQ(0u, clients_
[i
]->freed_frame_count());
185 // Create the maximum number of frames, all non-visible. They should not
186 // be evicted, because the previous frames were cleaned up at destruction.
187 AllocateClients(MaxNumberOfSavedFrames());
188 for (size_t i
= 0; i
< clients_
.size(); ++i
) {
189 cc::SoftwareFrameData frame
;
190 bool swap_result
= clients_
[i
]->SwapToNewFrame(static_cast<uint32
>(i
), 0);
191 clients_
[i
]->software_frame_manager()->SwapToNewFrameComplete(true);
192 EXPECT_TRUE(swap_result
);
193 EXPECT_EQ(0u, clients_
[i
]->evicted_frame_count());
194 EXPECT_EQ(0u, clients_
[i
]->freed_frame_count());
196 for (size_t i
= 0; i
< clients_
.size(); ++i
) {
197 EXPECT_EQ(0u, clients_
[i
]->evicted_frame_count());
198 EXPECT_EQ(0u, clients_
[i
]->freed_frame_count());
205 TEST_F(SoftwareFrameManagerTest
, EvictVersusFree
) {
206 // Create twice as many frames as are allowed and swap a visible frame to all
207 // clients_. Because they are all visible, the should not be evicted.
208 AllocateClients(2 * MaxNumberOfSavedFrames());
209 for (size_t i
= 0; i
< clients_
.size(); ++i
) {
210 clients_
[i
]->SwapToNewFrame(static_cast<uint32
>(i
), 0);
211 clients_
[i
]->software_frame_manager()->SwapToNewFrameComplete(true);
214 // Create a test client with a frame that is not evicted.
215 scoped_ptr
<FakeSoftwareFrameManagerClient
> test_client(
216 new FakeSoftwareFrameManagerClient
);
217 bool swap_result
= test_client
->SwapToNewFrame(static_cast<uint32
>(500), 0);
218 EXPECT_TRUE(swap_result
);
219 test_client
->software_frame_manager()->SwapToNewFrameComplete(true);
220 EXPECT_EQ(0u, test_client
->evicted_frame_count());
221 EXPECT_EQ(0u, test_client
->freed_frame_count());
223 // Take out a reference on the current frame and make the memory manager
224 // evict it. The frame will not be freed until this reference is released.
225 cc::TextureMailbox mailbox
;
226 scoped_ptr
<cc::SingleReleaseCallback
> callback
;
227 test_client
->software_frame_manager()->GetCurrentFrameMailbox(
228 &mailbox
, &callback
);
229 test_client
->software_frame_manager()->SetVisibility(false);
230 EXPECT_EQ(1u, test_client
->evicted_frame_count());
231 EXPECT_EQ(0u, test_client
->freed_frame_count());
233 // Swap a few frames. The frames will be freed as they are swapped out.
234 for (size_t frame
= 0; frame
< 10; ++frame
) {
235 bool swap_result
= test_client
->SwapToNewFrame(
236 static_cast<uint32
>(500), 1 + static_cast<int>(frame
));
237 EXPECT_TRUE(swap_result
);
238 test_client
->software_frame_manager()->SwapToNewFrameComplete(true);
239 EXPECT_EQ(frame
, test_client
->freed_frame_count());
240 EXPECT_EQ(1u, test_client
->evicted_frame_count());
243 // The reference to the frame that we didn't free is in the callback
244 // object. It will go away when the callback is destroyed.
245 EXPECT_EQ(9u, test_client
->freed_frame_count());
246 EXPECT_EQ(1u, test_client
->evicted_frame_count());
247 callback
->Run(0, false);
249 EXPECT_EQ(10u, test_client
->freed_frame_count());
250 EXPECT_EQ(1u, test_client
->evicted_frame_count());
255 } // namespace content