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
{
24 uint64_t ClientTracingId() const override
{ return 0; }
25 int ClientId() const override
{ return 0; }
26 uint64_t ShareGroupTracingGUID() const override
{ return 0; }
29 ~FakeMemoryTracker() override
{}
34 // This class is used to collect all stub assignments during a
36 class ClientAssignmentCollector
{
38 struct ClientMemoryStat
{
39 MemoryAllocation allocation
;
41 typedef base::hash_map
<GpuMemoryManagerClient
*, ClientMemoryStat
>
44 static const ClientMemoryStatMap
& GetClientStatsForLastManage() {
45 return client_memory_stats_for_last_manage_
;
47 static void ClearAllStats() {
48 client_memory_stats_for_last_manage_
.clear();
50 static void AddClientStat(GpuMemoryManagerClient
* client
,
51 const MemoryAllocation
& allocation
) {
52 DCHECK(!client_memory_stats_for_last_manage_
.count(client
));
53 client_memory_stats_for_last_manage_
[client
].allocation
= allocation
;
57 static ClientMemoryStatMap client_memory_stats_for_last_manage_
;
60 ClientAssignmentCollector::ClientMemoryStatMap
61 ClientAssignmentCollector::client_memory_stats_for_last_manage_
;
63 class FakeClient
: public GpuMemoryManagerClient
{
65 GpuMemoryManager
* memmgr_
;
66 bool suggest_have_frontbuffer_
;
67 MemoryAllocation allocation_
;
68 uint64 total_gpu_memory_
;
69 gfx::Size surface_size_
;
70 GpuMemoryManagerClient
* share_group_
;
71 scoped_refptr
<gpu::gles2::MemoryTracker
> memory_tracker_
;
72 scoped_ptr
<GpuMemoryTrackingGroup
> tracking_group_
;
73 scoped_ptr
<GpuMemoryManagerClientState
> client_state_
;
75 // This will create a client with no surface
76 FakeClient(GpuMemoryManager
* memmgr
, GpuMemoryManagerClient
* share_group
)
78 suggest_have_frontbuffer_(false),
80 share_group_(share_group
),
81 memory_tracker_(NULL
) {
83 memory_tracker_
= new FakeMemoryTracker();
84 tracking_group_
.reset(
85 memmgr_
->CreateTrackingGroup(0, memory_tracker_
.get()));
87 client_state_
.reset(memmgr_
->CreateClientState(this, false, true));
90 // This will create a client with a surface
91 FakeClient(GpuMemoryManager
* memmgr
, int32 surface_id
, bool visible
)
93 suggest_have_frontbuffer_(false),
96 memory_tracker_(NULL
) {
97 memory_tracker_
= new FakeMemoryTracker();
98 tracking_group_
.reset(
99 memmgr_
->CreateTrackingGroup(0, memory_tracker_
.get()));
101 memmgr_
->CreateClientState(this, surface_id
!= 0, visible
));
104 ~FakeClient() override
{
105 client_state_
.reset();
106 tracking_group_
.reset();
107 memory_tracker_
= NULL
;
110 void SetMemoryAllocation(const MemoryAllocation
& alloc
) override
{
112 ClientAssignmentCollector::AddClientStat(this, alloc
);
115 void SuggestHaveFrontBuffer(bool suggest_have_frontbuffer
) override
{
116 suggest_have_frontbuffer_
= suggest_have_frontbuffer
;
119 bool GetTotalGpuMemory(uint64
* bytes
) override
{
120 if (total_gpu_memory_
) {
121 *bytes
= total_gpu_memory_
;
126 void SetTotalGpuMemory(uint64 bytes
) { total_gpu_memory_
= bytes
; }
128 gpu::gles2::MemoryTracker
* GetMemoryTracker() const override
{
130 return share_group_
->GetMemoryTracker();
131 return memory_tracker_
.get();
134 gfx::Size
GetSurfaceSize() const override
{ return surface_size_
; }
135 void SetSurfaceSize(gfx::Size size
) { surface_size_
= size
; }
137 void SetVisible(bool visible
) {
138 client_state_
->SetVisible(visible
);
141 uint64
BytesWhenVisible() const {
142 return allocation_
.bytes_limit_when_visible
;
146 class GpuMemoryManagerTest
: public testing::Test
{
148 static const uint64 kFrontbufferLimitForTest
= 3;
150 GpuMemoryManagerTest()
151 : memmgr_(0, kFrontbufferLimitForTest
) {
152 memmgr_
.TestingDisableScheduleManage();
155 void SetUp() override
{}
157 static int32
GenerateUniqueSurfaceId() {
158 static int32 surface_id_
= 1;
159 return surface_id_
++;
162 bool IsAllocationForegroundForSurfaceYes(
163 const MemoryAllocation
& alloc
) {
166 bool IsAllocationBackgroundForSurfaceYes(
167 const MemoryAllocation
& alloc
) {
170 bool IsAllocationHibernatedForSurfaceYes(
171 const MemoryAllocation
& alloc
) {
174 bool IsAllocationForegroundForSurfaceNo(
175 const MemoryAllocation
& alloc
) {
176 return alloc
.bytes_limit_when_visible
!= 0;
178 bool IsAllocationBackgroundForSurfaceNo(
179 const MemoryAllocation
& alloc
) {
180 return alloc
.bytes_limit_when_visible
!= 0;
182 bool IsAllocationHibernatedForSurfaceNo(
183 const MemoryAllocation
& alloc
) {
184 return alloc
.bytes_limit_when_visible
== 0;
188 ClientAssignmentCollector::ClearAllStats();
192 GpuMemoryManager memmgr_
;
195 // Test GpuMemoryManager::Manage basic functionality.
196 // Expect memory allocation to set suggest_have_frontbuffer/backbuffer
197 // according to visibility and last used time for stubs with surface.
198 // Expect memory allocation to be shared according to share groups for stubs
199 // without a surface.
200 TEST_F(GpuMemoryManagerTest
, TestManageBasicFunctionality
) {
201 // Test stubs with surface.
202 FakeClient
stub1(&memmgr_
, GenerateUniqueSurfaceId(), true),
203 stub2(&memmgr_
, GenerateUniqueSurfaceId(), false);
206 EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub1
.allocation_
));
207 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2
.allocation_
));
209 // Test stubs without surface, with share group of 1 stub.
210 FakeClient
stub3(&memmgr_
, &stub1
), stub4(&memmgr_
, &stub2
);
213 EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub1
.allocation_
));
214 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2
.allocation_
));
215 EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub3
.allocation_
));
216 EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub4
.allocation_
));
218 // Test stub without surface, with share group of multiple stubs.
219 FakeClient
stub5(&memmgr_
, &stub2
);
222 EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub4
.allocation_
));
225 // Test GpuMemoryManager::Manage functionality: changing visibility.
226 // Expect memory allocation to set suggest_have_frontbuffer/backbuffer
227 // according to visibility and last used time for stubs with surface.
228 // Expect memory allocation to be shared according to share groups for stubs
229 // without a surface.
230 TEST_F(GpuMemoryManagerTest
, TestManageChangingVisibility
) {
231 FakeClient
stub1(&memmgr_
, GenerateUniqueSurfaceId(), true),
232 stub2(&memmgr_
, GenerateUniqueSurfaceId(), false);
234 FakeClient
stub3(&memmgr_
, &stub1
), stub4(&memmgr_
, &stub2
);
235 FakeClient
stub5(&memmgr_
, &stub2
);
238 EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub1
.allocation_
));
239 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2
.allocation_
));
240 EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub3
.allocation_
));
241 EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub4
.allocation_
));
242 EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub5
.allocation_
));
244 stub1
.SetVisible(false);
245 stub2
.SetVisible(true);
248 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub1
.allocation_
));
249 EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub2
.allocation_
));
250 EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub3
.allocation_
));
251 EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub4
.allocation_
));
252 EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub5
.allocation_
));
255 // Test GpuMemoryManager::Manage functionality: Test more than threshold number
257 // Expect all allocations to continue to have frontbuffer.
258 TEST_F(GpuMemoryManagerTest
, TestManageManyVisibleStubs
) {
259 FakeClient
stub1(&memmgr_
, GenerateUniqueSurfaceId(), true),
260 stub2(&memmgr_
, GenerateUniqueSurfaceId(), true),
261 stub3(&memmgr_
, GenerateUniqueSurfaceId(), true),
262 stub4(&memmgr_
, GenerateUniqueSurfaceId(), true);
264 FakeClient
stub5(&memmgr_
, &stub1
), stub6(&memmgr_
, &stub2
);
265 FakeClient
stub7(&memmgr_
, &stub2
);
268 EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub1
.allocation_
));
269 EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub2
.allocation_
));
270 EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub3
.allocation_
));
271 EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub4
.allocation_
));
272 EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub5
.allocation_
));
273 EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub6
.allocation_
));
274 EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub7
.allocation_
));
277 // Test GpuMemoryManager::Manage functionality: Test more than threshold number
278 // of not visible stubs.
279 // Expect the stubs surpassing the threshold to not have a backbuffer.
280 TEST_F(GpuMemoryManagerTest
, TestManageManyNotVisibleStubs
) {
281 FakeClient
stub1(&memmgr_
, GenerateUniqueSurfaceId(), true),
282 stub2(&memmgr_
, GenerateUniqueSurfaceId(), true),
283 stub3(&memmgr_
, GenerateUniqueSurfaceId(), true),
284 stub4(&memmgr_
, GenerateUniqueSurfaceId(), true);
285 stub4
.SetVisible(false);
286 stub3
.SetVisible(false);
287 stub2
.SetVisible(false);
288 stub1
.SetVisible(false);
290 FakeClient
stub5(&memmgr_
, &stub1
), stub6(&memmgr_
, &stub4
);
291 FakeClient
stub7(&memmgr_
, &stub1
);
294 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub1
.allocation_
));
295 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2
.allocation_
));
296 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub3
.allocation_
));
297 EXPECT_TRUE(IsAllocationHibernatedForSurfaceYes(stub4
.allocation_
));
298 EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub5
.allocation_
));
299 EXPECT_TRUE(IsAllocationHibernatedForSurfaceNo(stub6
.allocation_
));
300 EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub7
.allocation_
));
303 // Test GpuMemoryManager::Manage functionality: Test changing the last used
304 // time of stubs when doing so causes change in which stubs surpass threshold.
305 // Expect frontbuffer to be dropped for the older stub.
306 TEST_F(GpuMemoryManagerTest
, TestManageChangingLastUsedTime
) {
307 FakeClient
stub1(&memmgr_
, GenerateUniqueSurfaceId(), true),
308 stub2(&memmgr_
, GenerateUniqueSurfaceId(), true),
309 stub3(&memmgr_
, GenerateUniqueSurfaceId(), true),
310 stub4(&memmgr_
, GenerateUniqueSurfaceId(), true);
312 FakeClient
stub5(&memmgr_
, &stub3
), stub6(&memmgr_
, &stub4
);
313 FakeClient
stub7(&memmgr_
, &stub3
);
315 // Make stub4 be the least-recently-used client
316 stub4
.SetVisible(false);
317 stub3
.SetVisible(false);
318 stub2
.SetVisible(false);
319 stub1
.SetVisible(false);
322 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub1
.allocation_
));
323 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2
.allocation_
));
324 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub3
.allocation_
));
325 EXPECT_TRUE(IsAllocationHibernatedForSurfaceYes(stub4
.allocation_
));
326 EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub5
.allocation_
));
327 EXPECT_TRUE(IsAllocationHibernatedForSurfaceNo(stub6
.allocation_
));
328 EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub7
.allocation_
));
330 // Make stub3 become the least-recently-used client.
331 stub2
.SetVisible(true);
332 stub2
.SetVisible(false);
333 stub4
.SetVisible(true);
334 stub4
.SetVisible(false);
337 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub1
.allocation_
));
338 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2
.allocation_
));
339 EXPECT_TRUE(IsAllocationHibernatedForSurfaceYes(stub3
.allocation_
));
340 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub4
.allocation_
));
341 EXPECT_TRUE(IsAllocationHibernatedForSurfaceNo(stub5
.allocation_
));
342 EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub6
.allocation_
));
343 EXPECT_TRUE(IsAllocationHibernatedForSurfaceNo(stub7
.allocation_
));
346 // Test GpuMemoryManager::Manage functionality: Test changing importance of
347 // enough stubs so that every stub in share group crosses threshold.
348 // Expect memory allocation of the stubs without surface to share memory
349 // allocation with the most visible stub in share group.
350 TEST_F(GpuMemoryManagerTest
, TestManageChangingImportanceShareGroup
) {
351 FakeClient
stub_ignore_a(&memmgr_
, GenerateUniqueSurfaceId(), true),
352 stub_ignore_b(&memmgr_
, GenerateUniqueSurfaceId(), false),
353 stub_ignore_c(&memmgr_
, GenerateUniqueSurfaceId(), false);
354 FakeClient
stub1(&memmgr_
, GenerateUniqueSurfaceId(), false),
355 stub2(&memmgr_
, GenerateUniqueSurfaceId(), false);
357 FakeClient
stub3(&memmgr_
, &stub2
), stub4(&memmgr_
, &stub2
);
359 // stub1 and stub2 keep their non-hibernated state because they're
360 // either visible or the 2 most recently used clients (through the
361 // first three checks).
362 stub1
.SetVisible(true);
363 stub2
.SetVisible(true);
365 EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub1
.allocation_
));
366 EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub2
.allocation_
));
367 EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub3
.allocation_
));
368 EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub4
.allocation_
));
370 stub1
.SetVisible(false);
372 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub1
.allocation_
));
373 EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub2
.allocation_
));
374 EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub3
.allocation_
));
375 EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub4
.allocation_
));
377 stub2
.SetVisible(false);
379 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub1
.allocation_
));
380 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2
.allocation_
));
381 EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub3
.allocation_
));
382 EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub4
.allocation_
));
384 // stub_ignore_b will cause stub1 to become hibernated (because
385 // stub_ignore_a, stub_ignore_b, and stub2 are all non-hibernated and more
387 stub_ignore_b
.SetVisible(true);
388 stub_ignore_b
.SetVisible(false);
390 EXPECT_TRUE(IsAllocationHibernatedForSurfaceYes(stub1
.allocation_
));
391 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2
.allocation_
));
392 EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub3
.allocation_
));
393 EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub4
.allocation_
));
395 // stub_ignore_c will cause stub2 to become hibernated (because
396 // stub_ignore_a, stub_ignore_b, and stub_ignore_c are all non-hibernated
397 // and more important).
398 stub_ignore_c
.SetVisible(true);
399 stub_ignore_c
.SetVisible(false);
401 EXPECT_TRUE(IsAllocationHibernatedForSurfaceYes(stub1
.allocation_
));
402 EXPECT_TRUE(IsAllocationHibernatedForSurfaceYes(stub2
.allocation_
));
403 EXPECT_TRUE(IsAllocationHibernatedForSurfaceNo(stub3
.allocation_
));
404 EXPECT_TRUE(IsAllocationHibernatedForSurfaceNo(stub4
.allocation_
));
407 } // namespace content