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/memory/scoped_vector.h"
10 #include "base/memory/shared_memory.h"
11 #include "base/sys_info.h"
12 #include "content/common/host_shared_bitmap_manager.h"
13 #include "testing/gtest/include/gtest/gtest.h"
17 class FakeSoftwareFrameManagerClient
: public SoftwareFrameManagerClient
{
19 FakeSoftwareFrameManagerClient()
20 : evicted_count_(0), weak_ptr_factory_(this) {
21 software_frame_manager_
.reset(new SoftwareFrameManager(
22 weak_ptr_factory_
.GetWeakPtr()));
24 virtual ~FakeSoftwareFrameManagerClient() {
25 HostSharedBitmapManager::current()->ProcessRemoved(
26 base::GetCurrentProcessHandle());
28 virtual void SoftwareFrameWasFreed(uint32 output_surface_id
,
29 unsigned frame_id
) OVERRIDE
{
30 freed_frames_
.push_back(std::make_pair(output_surface_id
, frame_id
));
32 virtual void ReleaseReferencesToSoftwareFrame() OVERRIDE
{
36 bool SwapToNewFrame(uint32 output_surface
, unsigned frame_id
) {
37 cc::SoftwareFrameData frame
;
39 frame
.size
= gfx::Size(1, 1);
40 frame
.damage_rect
= gfx::Rect(frame
.size
);
41 frame
.bitmap_id
= cc::SharedBitmap::GenerateId();
42 scoped_ptr
<base::SharedMemory
> memory
=
43 make_scoped_ptr(new base::SharedMemory
);
44 memory
->CreateAnonymous(4);
45 HostSharedBitmapManager::current()->ChildAllocatedSharedBitmap(
46 4, memory
->handle(), base::GetCurrentProcessHandle(), frame
.bitmap_id
);
47 allocated_memory_
.push_back(memory
.release());
48 return software_frame_manager_
->SwapToNewFrame(
49 output_surface
, &frame
, 1.0, base::GetCurrentProcessHandle());
52 SoftwareFrameManager
* software_frame_manager() {
53 return software_frame_manager_
.get();
55 size_t freed_frame_count() const { return freed_frames_
.size(); }
56 size_t evicted_frame_count() const { return evicted_count_
; }
59 std::vector
<std::pair
<uint32
,unsigned> > freed_frames_
;
60 size_t evicted_count_
;
61 ScopedVector
<base::SharedMemory
> allocated_memory_
;
63 scoped_ptr
<SoftwareFrameManager
> software_frame_manager_
;
64 base::WeakPtrFactory
<FakeSoftwareFrameManagerClient
>
67 DISALLOW_COPY_AND_ASSIGN(FakeSoftwareFrameManagerClient
);
70 class SoftwareFrameManagerTest
: public testing::Test
{
72 SoftwareFrameManagerTest() {}
73 void AllocateClients(size_t num_clients
) {
74 for (size_t i
= 0; i
< num_clients
; ++i
)
75 clients_
.push_back(new FakeSoftwareFrameManagerClient
);
78 for (size_t i
= 0; i
< clients_
.size(); ++i
)
82 size_t MaxNumberOfSavedFrames() const {
84 RendererFrameManager::GetInstance()->max_number_of_saved_frames();
89 std::vector
<FakeSoftwareFrameManagerClient
*> clients_
;
92 DISALLOW_COPY_AND_ASSIGN(SoftwareFrameManagerTest
);
95 TEST_F(SoftwareFrameManagerTest
, DoNotEvictVisible
) {
96 // Create twice as many frames as are allowed.
97 AllocateClients(2 * MaxNumberOfSavedFrames());
99 // Swap a visible frame to all clients_. Because they are all visible,
100 // the should not be evicted.
101 for (size_t i
= 0; i
< clients_
.size(); ++i
) {
102 bool swap_result
= clients_
[i
]->SwapToNewFrame(
103 static_cast<uint32
>(i
), 0);
104 clients_
[i
]->software_frame_manager()->SwapToNewFrameComplete(true);
105 EXPECT_TRUE(swap_result
);
106 EXPECT_EQ(0u, clients_
[i
]->evicted_frame_count());
107 EXPECT_EQ(0u, clients_
[i
]->freed_frame_count());
109 for (size_t i
= 0; i
< clients_
.size(); ++i
) {
110 EXPECT_EQ(0u, clients_
[i
]->evicted_frame_count());
111 EXPECT_EQ(0u, clients_
[i
]->freed_frame_count());
114 // Swap another frame and make sure the original was freed (but not evicted).
115 for (size_t i
= 0; i
< clients_
.size(); ++i
) {
116 bool swap_result
= clients_
[i
]->SwapToNewFrame(
117 static_cast<uint32
>(i
), 1);
118 clients_
[i
]->software_frame_manager()->SwapToNewFrameComplete(true);
119 EXPECT_TRUE(swap_result
);
120 EXPECT_EQ(0u, clients_
[i
]->evicted_frame_count());
121 EXPECT_EQ(1u, clients_
[i
]->freed_frame_count());
123 for (size_t i
= 0; i
< clients_
.size(); ++i
) {
124 EXPECT_EQ(0u, clients_
[i
]->evicted_frame_count());
125 EXPECT_EQ(1u, clients_
[i
]->freed_frame_count());
128 // Mark the frames as nonvisible and make sure they start getting evicted.
129 for (size_t i
= 0; i
< clients_
.size(); ++i
) {
130 clients_
[i
]->software_frame_manager()->SetVisibility(false);
131 if (clients_
.size() - i
> MaxNumberOfSavedFrames()) {
132 EXPECT_EQ(1u, clients_
[i
]->evicted_frame_count());
133 EXPECT_EQ(2u, clients_
[i
]->freed_frame_count());
135 EXPECT_EQ(0u, clients_
[i
]->evicted_frame_count());
136 EXPECT_EQ(1u, clients_
[i
]->freed_frame_count());
144 TEST_F(SoftwareFrameManagerTest
, DoNotEvictDuringSwap
) {
145 // Create twice as many frames as are allowed.
146 AllocateClients(2 * MaxNumberOfSavedFrames());
148 // Swap a visible frame to all clients_. Because they are all visible,
149 // the should not be evicted.
150 for (size_t i
= 0; i
< clients_
.size(); ++i
) {
151 bool swap_result
= clients_
[i
]->SwapToNewFrame(static_cast<uint32
>(i
), 0);
152 clients_
[i
]->software_frame_manager()->SwapToNewFrameComplete(true);
153 EXPECT_TRUE(swap_result
);
154 EXPECT_EQ(0u, clients_
[i
]->evicted_frame_count());
155 EXPECT_EQ(0u, clients_
[i
]->freed_frame_count());
157 for (size_t i
= 0; i
< clients_
.size(); ++i
) {
158 EXPECT_EQ(0u, clients_
[i
]->evicted_frame_count());
159 EXPECT_EQ(0u, clients_
[i
]->freed_frame_count());
162 // Now create a test non-visible client, and swap a non-visible frame in.
163 scoped_ptr
<FakeSoftwareFrameManagerClient
> test_client(
164 new FakeSoftwareFrameManagerClient
);
165 test_client
->software_frame_manager()->SetVisibility(false);
167 bool swap_result
= test_client
->SwapToNewFrame(
168 static_cast<uint32
>(500), 0);
169 EXPECT_TRUE(swap_result
);
170 EXPECT_EQ(0u, test_client
->evicted_frame_count());
171 EXPECT_EQ(0u, test_client
->freed_frame_count());
172 test_client
->software_frame_manager()->SwapToNewFrameComplete(false);
173 EXPECT_EQ(1u, test_client
->evicted_frame_count());
174 EXPECT_EQ(1u, test_client
->freed_frame_count());
181 TEST_F(SoftwareFrameManagerTest
, Cleanup
) {
182 // Create twice as many frames as are allowed.
183 AllocateClients(2 * MaxNumberOfSavedFrames());
185 // Swap a visible frame to all clients_. Because they are all visible,
186 // the should not be evicted.
187 for (size_t i
= 0; i
< clients_
.size(); ++i
) {
188 bool swap_result
= clients_
[i
]->SwapToNewFrame(static_cast<uint32
>(i
), 0);
189 clients_
[i
]->software_frame_manager()->SwapToNewFrameComplete(true);
190 EXPECT_TRUE(swap_result
);
191 EXPECT_EQ(0u, clients_
[i
]->evicted_frame_count());
192 EXPECT_EQ(0u, clients_
[i
]->freed_frame_count());
198 // Create the maximum number of frames, all non-visible. They should not
199 // be evicted, because the previous frames were cleaned up at destruction.
200 AllocateClients(MaxNumberOfSavedFrames());
201 for (size_t i
= 0; i
< clients_
.size(); ++i
) {
202 cc::SoftwareFrameData frame
;
203 bool swap_result
= clients_
[i
]->SwapToNewFrame(static_cast<uint32
>(i
), 0);
204 clients_
[i
]->software_frame_manager()->SwapToNewFrameComplete(true);
205 EXPECT_TRUE(swap_result
);
206 EXPECT_EQ(0u, clients_
[i
]->evicted_frame_count());
207 EXPECT_EQ(0u, clients_
[i
]->freed_frame_count());
209 for (size_t i
= 0; i
< clients_
.size(); ++i
) {
210 EXPECT_EQ(0u, clients_
[i
]->evicted_frame_count());
211 EXPECT_EQ(0u, clients_
[i
]->freed_frame_count());
218 TEST_F(SoftwareFrameManagerTest
, EvictVersusFree
) {
219 // Create twice as many frames as are allowed and swap a visible frame to all
220 // clients_. Because they are all visible, the should not be evicted.
221 AllocateClients(2 * MaxNumberOfSavedFrames());
222 for (size_t i
= 0; i
< clients_
.size(); ++i
) {
223 clients_
[i
]->SwapToNewFrame(static_cast<uint32
>(i
), 0);
224 clients_
[i
]->software_frame_manager()->SwapToNewFrameComplete(true);
227 // Create a test client with a frame that is not evicted.
228 scoped_ptr
<FakeSoftwareFrameManagerClient
> test_client(
229 new FakeSoftwareFrameManagerClient
);
230 bool swap_result
= test_client
->SwapToNewFrame(static_cast<uint32
>(500), 0);
231 EXPECT_TRUE(swap_result
);
232 test_client
->software_frame_manager()->SwapToNewFrameComplete(true);
233 EXPECT_EQ(0u, test_client
->evicted_frame_count());
234 EXPECT_EQ(0u, test_client
->freed_frame_count());
236 // Take out a reference on the current frame and make the memory manager
237 // evict it. The frame will not be freed until this reference is released.
238 cc::TextureMailbox mailbox
;
239 scoped_ptr
<cc::SingleReleaseCallback
> callback
;
240 test_client
->software_frame_manager()->GetCurrentFrameMailbox(
241 &mailbox
, &callback
);
242 test_client
->software_frame_manager()->SetVisibility(false);
243 EXPECT_EQ(1u, test_client
->evicted_frame_count());
244 EXPECT_EQ(0u, test_client
->freed_frame_count());
246 // Swap a few frames. The frames will be freed as they are swapped out.
247 for (size_t frame
= 0; frame
< 10; ++frame
) {
248 bool swap_result
= test_client
->SwapToNewFrame(
249 static_cast<uint32
>(500), 1 + static_cast<int>(frame
));
250 EXPECT_TRUE(swap_result
);
251 test_client
->software_frame_manager()->SwapToNewFrameComplete(true);
252 EXPECT_EQ(frame
, test_client
->freed_frame_count());
253 EXPECT_EQ(1u, test_client
->evicted_frame_count());
256 // The reference to the frame that we didn't free is in the callback
257 // object. It will go away when the callback is destroyed.
258 EXPECT_EQ(9u, test_client
->freed_frame_count());
259 EXPECT_EQ(1u, test_client
->evicted_frame_count());
260 callback
->Run(0, false);
262 EXPECT_EQ(10u, test_client
->freed_frame_count());
263 EXPECT_EQ(1u, test_client
->evicted_frame_count());
268 } // namespace content