GPU workaround to simulate Out of Memory errors with large textures
[chromium-blink-merge.git] / content / common / gpu / gpu_memory_manager_unittest.cc
blobd0237fb5ec0e876d4f7429aaff6dd40a7129a752
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 {
16 public:
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 {
22 return true;
24 private:
25 ~FakeMemoryTracker() override {}
28 namespace content {
30 // This class is used to collect all stub assignments during a
31 // Manage() call.
32 class ClientAssignmentCollector {
33 public:
34 struct ClientMemoryStat {
35 MemoryAllocation allocation;
37 typedef base::hash_map<GpuMemoryManagerClient*, ClientMemoryStat>
38 ClientMemoryStatMap;
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;
52 private:
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 {
60 public:
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)
73 : memmgr_(memmgr),
74 suggest_have_frontbuffer_(false),
75 total_gpu_memory_(0),
76 share_group_(share_group),
77 memory_tracker_(NULL) {
78 if (!share_group_) {
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)
88 : memmgr_(memmgr),
89 suggest_have_frontbuffer_(false),
90 total_gpu_memory_(0),
91 share_group_(NULL),
92 memory_tracker_(NULL) {
93 memory_tracker_ = new FakeMemoryTracker();
94 tracking_group_.reset(
95 memmgr_->CreateTrackingGroup(0, memory_tracker_.get()));
96 client_state_.reset(
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 {
107 allocation_ = alloc;
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_;
118 return true;
120 return false;
122 void SetTotalGpuMemory(uint64 bytes) { total_gpu_memory_ = bytes; }
124 gpu::gles2::MemoryTracker* GetMemoryTracker() const override {
125 if (share_group_)
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 {
143 protected:
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) {
160 return true;
162 bool IsAllocationBackgroundForSurfaceYes(
163 const MemoryAllocation& alloc) {
164 return true;
166 bool IsAllocationHibernatedForSurfaceYes(
167 const MemoryAllocation& alloc) {
168 return true;
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;
183 void Manage() {
184 ClientAssignmentCollector::ClearAllStats();
185 memmgr_.Manage();
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);
201 Manage();
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);
208 Manage();
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);
217 Manage();
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);
233 Manage();
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);
243 Manage();
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
252 // of visible stubs.
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);
263 Manage();
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);
289 Manage();
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);
317 Manage();
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);
332 Manage();
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);
360 Manage();
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);
367 Manage();
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);
374 Manage();
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
382 // important).
383 stub_ignore_b.SetVisible(true);
384 stub_ignore_b.SetVisible(false);
385 Manage();
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);
396 Manage();
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