1 // Copyright (c) 2012 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/common/gpu/gpu_memory_manager.h"
7 #include "content/common/gpu/gpu_memory_manager_client.h"
8 #include "content/common/gpu/gpu_memory_tracking.h"
9 #include "gpu/command_buffer/common/gpu_memory_allocation.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11 #include "ui/gfx/geometry/size_conversions.h"
13 using gpu::MemoryAllocation
;
15 class FakeMemoryTracker
: public gpu::gles2::MemoryTracker
{
17 void TrackMemoryAllocatedChange(
18 size_t /* old_size */,
19 size_t /* new_size */,
20 gpu::gles2::MemoryTracker::Pool
/* pool */) override
{}
21 bool EnsureGPUMemoryAvailable(size_t /* size_needed */) override
{
25 ~FakeMemoryTracker() override
{}
30 // This class is used to collect all stub assignments during a
32 class ClientAssignmentCollector
{
34 struct ClientMemoryStat
{
35 MemoryAllocation allocation
;
37 typedef base::hash_map
<GpuMemoryManagerClient
*, ClientMemoryStat
>
40 static const ClientMemoryStatMap
& GetClientStatsForLastManage() {
41 return client_memory_stats_for_last_manage_
;
43 static void ClearAllStats() {
44 client_memory_stats_for_last_manage_
.clear();
46 static void AddClientStat(GpuMemoryManagerClient
* client
,
47 const MemoryAllocation
& allocation
) {
48 DCHECK(!client_memory_stats_for_last_manage_
.count(client
));
49 client_memory_stats_for_last_manage_
[client
].allocation
= allocation
;
53 static ClientMemoryStatMap client_memory_stats_for_last_manage_
;
56 ClientAssignmentCollector::ClientMemoryStatMap
57 ClientAssignmentCollector::client_memory_stats_for_last_manage_
;
59 class FakeClient
: public GpuMemoryManagerClient
{
61 GpuMemoryManager
* memmgr_
;
62 bool suggest_have_frontbuffer_
;
63 MemoryAllocation allocation_
;
64 uint64 total_gpu_memory_
;
65 gfx::Size surface_size_
;
66 GpuMemoryManagerClient
* share_group_
;
67 scoped_refptr
<gpu::gles2::MemoryTracker
> memory_tracker_
;
68 scoped_ptr
<GpuMemoryTrackingGroup
> tracking_group_
;
69 scoped_ptr
<GpuMemoryManagerClientState
> client_state_
;
71 // This will create a client with no surface
72 FakeClient(GpuMemoryManager
* memmgr
, GpuMemoryManagerClient
* share_group
)
74 suggest_have_frontbuffer_(false),
76 share_group_(share_group
),
77 memory_tracker_(NULL
) {
79 memory_tracker_
= new FakeMemoryTracker();
80 tracking_group_
.reset(
81 memmgr_
->CreateTrackingGroup(0, memory_tracker_
.get()));
83 client_state_
.reset(memmgr_
->CreateClientState(this, false, true));
86 // This will create a client with a surface
87 FakeClient(GpuMemoryManager
* memmgr
, int32 surface_id
, bool visible
)
89 suggest_have_frontbuffer_(false),
92 memory_tracker_(NULL
) {
93 memory_tracker_
= new FakeMemoryTracker();
94 tracking_group_
.reset(
95 memmgr_
->CreateTrackingGroup(0, memory_tracker_
.get()));
97 memmgr_
->CreateClientState(this, surface_id
!= 0, visible
));
100 ~FakeClient() override
{
101 client_state_
.reset();
102 tracking_group_
.reset();
103 memory_tracker_
= NULL
;
106 void SetMemoryAllocation(const MemoryAllocation
& alloc
) override
{
108 ClientAssignmentCollector::AddClientStat(this, alloc
);
111 void SuggestHaveFrontBuffer(bool suggest_have_frontbuffer
) override
{
112 suggest_have_frontbuffer_
= suggest_have_frontbuffer
;
115 bool GetTotalGpuMemory(uint64
* bytes
) override
{
116 if (total_gpu_memory_
) {
117 *bytes
= total_gpu_memory_
;
122 void SetTotalGpuMemory(uint64 bytes
) { total_gpu_memory_
= bytes
; }
124 gpu::gles2::MemoryTracker
* GetMemoryTracker() const override
{
126 return share_group_
->GetMemoryTracker();
127 return memory_tracker_
.get();
130 gfx::Size
GetSurfaceSize() const override
{ return surface_size_
; }
131 void SetSurfaceSize(gfx::Size size
) { surface_size_
= size
; }
133 void SetVisible(bool visible
) {
134 client_state_
->SetVisible(visible
);
137 uint64
BytesWhenVisible() const {
138 return allocation_
.bytes_limit_when_visible
;
142 class GpuMemoryManagerTest
: public testing::Test
{
144 static const uint64 kFrontbufferLimitForTest
= 3;
146 GpuMemoryManagerTest()
147 : memmgr_(0, kFrontbufferLimitForTest
) {
148 memmgr_
.TestingDisableScheduleManage();
151 void SetUp() override
{}
153 static int32
GenerateUniqueSurfaceId() {
154 static int32 surface_id_
= 1;
155 return surface_id_
++;
158 bool IsAllocationForegroundForSurfaceYes(
159 const MemoryAllocation
& alloc
) {
162 bool IsAllocationBackgroundForSurfaceYes(
163 const MemoryAllocation
& alloc
) {
166 bool IsAllocationHibernatedForSurfaceYes(
167 const MemoryAllocation
& alloc
) {
170 bool IsAllocationForegroundForSurfaceNo(
171 const MemoryAllocation
& alloc
) {
172 return alloc
.bytes_limit_when_visible
!= 0;
174 bool IsAllocationBackgroundForSurfaceNo(
175 const MemoryAllocation
& alloc
) {
176 return alloc
.bytes_limit_when_visible
!= 0;
178 bool IsAllocationHibernatedForSurfaceNo(
179 const MemoryAllocation
& alloc
) {
180 return alloc
.bytes_limit_when_visible
== 0;
184 ClientAssignmentCollector::ClearAllStats();
188 GpuMemoryManager memmgr_
;
191 // Test GpuMemoryManager::Manage basic functionality.
192 // Expect memory allocation to set suggest_have_frontbuffer/backbuffer
193 // according to visibility and last used time for stubs with surface.
194 // Expect memory allocation to be shared according to share groups for stubs
195 // without a surface.
196 TEST_F(GpuMemoryManagerTest
, TestManageBasicFunctionality
) {
197 // Test stubs with surface.
198 FakeClient
stub1(&memmgr_
, GenerateUniqueSurfaceId(), true),
199 stub2(&memmgr_
, GenerateUniqueSurfaceId(), false);
202 EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub1
.allocation_
));
203 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2
.allocation_
));
205 // Test stubs without surface, with share group of 1 stub.
206 FakeClient
stub3(&memmgr_
, &stub1
), stub4(&memmgr_
, &stub2
);
209 EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub1
.allocation_
));
210 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2
.allocation_
));
211 EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub3
.allocation_
));
212 EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub4
.allocation_
));
214 // Test stub without surface, with share group of multiple stubs.
215 FakeClient
stub5(&memmgr_
, &stub2
);
218 EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub4
.allocation_
));
221 // Test GpuMemoryManager::Manage functionality: changing visibility.
222 // Expect memory allocation to set suggest_have_frontbuffer/backbuffer
223 // according to visibility and last used time for stubs with surface.
224 // Expect memory allocation to be shared according to share groups for stubs
225 // without a surface.
226 TEST_F(GpuMemoryManagerTest
, TestManageChangingVisibility
) {
227 FakeClient
stub1(&memmgr_
, GenerateUniqueSurfaceId(), true),
228 stub2(&memmgr_
, GenerateUniqueSurfaceId(), false);
230 FakeClient
stub3(&memmgr_
, &stub1
), stub4(&memmgr_
, &stub2
);
231 FakeClient
stub5(&memmgr_
, &stub2
);
234 EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub1
.allocation_
));
235 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2
.allocation_
));
236 EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub3
.allocation_
));
237 EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub4
.allocation_
));
238 EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub5
.allocation_
));
240 stub1
.SetVisible(false);
241 stub2
.SetVisible(true);
244 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub1
.allocation_
));
245 EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub2
.allocation_
));
246 EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub3
.allocation_
));
247 EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub4
.allocation_
));
248 EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub5
.allocation_
));
251 // Test GpuMemoryManager::Manage functionality: Test more than threshold number
253 // Expect all allocations to continue to have frontbuffer.
254 TEST_F(GpuMemoryManagerTest
, TestManageManyVisibleStubs
) {
255 FakeClient
stub1(&memmgr_
, GenerateUniqueSurfaceId(), true),
256 stub2(&memmgr_
, GenerateUniqueSurfaceId(), true),
257 stub3(&memmgr_
, GenerateUniqueSurfaceId(), true),
258 stub4(&memmgr_
, GenerateUniqueSurfaceId(), true);
260 FakeClient
stub5(&memmgr_
, &stub1
), stub6(&memmgr_
, &stub2
);
261 FakeClient
stub7(&memmgr_
, &stub2
);
264 EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub1
.allocation_
));
265 EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub2
.allocation_
));
266 EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub3
.allocation_
));
267 EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub4
.allocation_
));
268 EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub5
.allocation_
));
269 EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub6
.allocation_
));
270 EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub7
.allocation_
));
273 // Test GpuMemoryManager::Manage functionality: Test more than threshold number
274 // of not visible stubs.
275 // Expect the stubs surpassing the threshold to not have a backbuffer.
276 TEST_F(GpuMemoryManagerTest
, TestManageManyNotVisibleStubs
) {
277 FakeClient
stub1(&memmgr_
, GenerateUniqueSurfaceId(), true),
278 stub2(&memmgr_
, GenerateUniqueSurfaceId(), true),
279 stub3(&memmgr_
, GenerateUniqueSurfaceId(), true),
280 stub4(&memmgr_
, GenerateUniqueSurfaceId(), true);
281 stub4
.SetVisible(false);
282 stub3
.SetVisible(false);
283 stub2
.SetVisible(false);
284 stub1
.SetVisible(false);
286 FakeClient
stub5(&memmgr_
, &stub1
), stub6(&memmgr_
, &stub4
);
287 FakeClient
stub7(&memmgr_
, &stub1
);
290 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub1
.allocation_
));
291 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2
.allocation_
));
292 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub3
.allocation_
));
293 EXPECT_TRUE(IsAllocationHibernatedForSurfaceYes(stub4
.allocation_
));
294 EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub5
.allocation_
));
295 EXPECT_TRUE(IsAllocationHibernatedForSurfaceNo(stub6
.allocation_
));
296 EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub7
.allocation_
));
299 // Test GpuMemoryManager::Manage functionality: Test changing the last used
300 // time of stubs when doing so causes change in which stubs surpass threshold.
301 // Expect frontbuffer to be dropped for the older stub.
302 TEST_F(GpuMemoryManagerTest
, TestManageChangingLastUsedTime
) {
303 FakeClient
stub1(&memmgr_
, GenerateUniqueSurfaceId(), true),
304 stub2(&memmgr_
, GenerateUniqueSurfaceId(), true),
305 stub3(&memmgr_
, GenerateUniqueSurfaceId(), true),
306 stub4(&memmgr_
, GenerateUniqueSurfaceId(), true);
308 FakeClient
stub5(&memmgr_
, &stub3
), stub6(&memmgr_
, &stub4
);
309 FakeClient
stub7(&memmgr_
, &stub3
);
311 // Make stub4 be the least-recently-used client
312 stub4
.SetVisible(false);
313 stub3
.SetVisible(false);
314 stub2
.SetVisible(false);
315 stub1
.SetVisible(false);
318 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub1
.allocation_
));
319 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2
.allocation_
));
320 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub3
.allocation_
));
321 EXPECT_TRUE(IsAllocationHibernatedForSurfaceYes(stub4
.allocation_
));
322 EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub5
.allocation_
));
323 EXPECT_TRUE(IsAllocationHibernatedForSurfaceNo(stub6
.allocation_
));
324 EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub7
.allocation_
));
326 // Make stub3 become the least-recently-used client.
327 stub2
.SetVisible(true);
328 stub2
.SetVisible(false);
329 stub4
.SetVisible(true);
330 stub4
.SetVisible(false);
333 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub1
.allocation_
));
334 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2
.allocation_
));
335 EXPECT_TRUE(IsAllocationHibernatedForSurfaceYes(stub3
.allocation_
));
336 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub4
.allocation_
));
337 EXPECT_TRUE(IsAllocationHibernatedForSurfaceNo(stub5
.allocation_
));
338 EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub6
.allocation_
));
339 EXPECT_TRUE(IsAllocationHibernatedForSurfaceNo(stub7
.allocation_
));
342 // Test GpuMemoryManager::Manage functionality: Test changing importance of
343 // enough stubs so that every stub in share group crosses threshold.
344 // Expect memory allocation of the stubs without surface to share memory
345 // allocation with the most visible stub in share group.
346 TEST_F(GpuMemoryManagerTest
, TestManageChangingImportanceShareGroup
) {
347 FakeClient
stub_ignore_a(&memmgr_
, GenerateUniqueSurfaceId(), true),
348 stub_ignore_b(&memmgr_
, GenerateUniqueSurfaceId(), false),
349 stub_ignore_c(&memmgr_
, GenerateUniqueSurfaceId(), false);
350 FakeClient
stub1(&memmgr_
, GenerateUniqueSurfaceId(), false),
351 stub2(&memmgr_
, GenerateUniqueSurfaceId(), false);
353 FakeClient
stub3(&memmgr_
, &stub2
), stub4(&memmgr_
, &stub2
);
355 // stub1 and stub2 keep their non-hibernated state because they're
356 // either visible or the 2 most recently used clients (through the
357 // first three checks).
358 stub1
.SetVisible(true);
359 stub2
.SetVisible(true);
361 EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub1
.allocation_
));
362 EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub2
.allocation_
));
363 EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub3
.allocation_
));
364 EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub4
.allocation_
));
366 stub1
.SetVisible(false);
368 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub1
.allocation_
));
369 EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub2
.allocation_
));
370 EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub3
.allocation_
));
371 EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub4
.allocation_
));
373 stub2
.SetVisible(false);
375 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub1
.allocation_
));
376 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2
.allocation_
));
377 EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub3
.allocation_
));
378 EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub4
.allocation_
));
380 // stub_ignore_b will cause stub1 to become hibernated (because
381 // stub_ignore_a, stub_ignore_b, and stub2 are all non-hibernated and more
383 stub_ignore_b
.SetVisible(true);
384 stub_ignore_b
.SetVisible(false);
386 EXPECT_TRUE(IsAllocationHibernatedForSurfaceYes(stub1
.allocation_
));
387 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2
.allocation_
));
388 EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub3
.allocation_
));
389 EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub4
.allocation_
));
391 // stub_ignore_c will cause stub2 to become hibernated (because
392 // stub_ignore_a, stub_ignore_b, and stub_ignore_c are all non-hibernated
393 // and more important).
394 stub_ignore_c
.SetVisible(true);
395 stub_ignore_c
.SetVisible(false);
397 EXPECT_TRUE(IsAllocationHibernatedForSurfaceYes(stub1
.allocation_
));
398 EXPECT_TRUE(IsAllocationHibernatedForSurfaceYes(stub2
.allocation_
));
399 EXPECT_TRUE(IsAllocationHibernatedForSurfaceNo(stub3
.allocation_
));
400 EXPECT_TRUE(IsAllocationHibernatedForSurfaceNo(stub4
.allocation_
));
403 } // namespace content