Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / content / common / gpu / gpu_memory_manager_unittest.cc
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.
4
5 #include "content/common/gpu/gpu_memory_manager.h"
6 #include "content/common/gpu/gpu_memory_manager_client.h"
7 #include "content/common/gpu/gpu_memory_tracking.h"
8 #include "gpu/command_buffer/common/gpu_memory_allocation.h"
9 #include "ui/gfx/size_conversions.h"
10
11 #include "testing/gtest/include/gtest/gtest.h"
12
13 using gpu::MemoryAllocation;
14
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;
23   }
24  private:
25   ~FakeMemoryTracker() override {}
26 };
27
28 namespace content {
29
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;
36   };
37   typedef base::hash_map<GpuMemoryManagerClient*, ClientMemoryStat>
38       ClientMemoryStatMap;
39
40   static const ClientMemoryStatMap& GetClientStatsForLastManage() {
41     return client_memory_stats_for_last_manage_;
42   }
43   static void ClearAllStats() {
44     client_memory_stats_for_last_manage_.clear();
45   }
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;
50   }
51
52  private:
53   static ClientMemoryStatMap client_memory_stats_for_last_manage_;
54 };
55
56 ClientAssignmentCollector::ClientMemoryStatMap
57     ClientAssignmentCollector::client_memory_stats_for_last_manage_;
58
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_;
70
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()));
82     }
83     client_state_.reset(memmgr_->CreateClientState(this, false, true));
84   }
85
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));
98   }
99
100   ~FakeClient() override {
101     client_state_.reset();
102     tracking_group_.reset();
103     memory_tracker_ = NULL;
104   }
105
106   void SetMemoryAllocation(const MemoryAllocation& alloc) override {
107     allocation_ = alloc;
108     ClientAssignmentCollector::AddClientStat(this, alloc);
109   }
110
111   void SuggestHaveFrontBuffer(bool suggest_have_frontbuffer) override {
112     suggest_have_frontbuffer_ = suggest_have_frontbuffer;
113   }
114
115   bool GetTotalGpuMemory(uint64* bytes) override {
116     if (total_gpu_memory_) {
117       *bytes = total_gpu_memory_;
118       return true;
119     }
120     return false;
121   }
122   void SetTotalGpuMemory(uint64 bytes) { total_gpu_memory_ = bytes; }
123
124   gpu::gles2::MemoryTracker* GetMemoryTracker() const override {
125     if (share_group_)
126       return share_group_->GetMemoryTracker();
127     return memory_tracker_.get();
128   }
129
130   gfx::Size GetSurfaceSize() const override { return surface_size_; }
131   void SetSurfaceSize(gfx::Size size) { surface_size_ = size; }
132
133   void SetVisible(bool visible) {
134     client_state_->SetVisible(visible);
135   }
136
137   uint64 BytesWhenVisible() const {
138     return allocation_.bytes_limit_when_visible;
139   }
140 };
141
142 class GpuMemoryManagerTest : public testing::Test {
143  protected:
144   static const uint64 kFrontbufferLimitForTest = 3;
145
146   GpuMemoryManagerTest()
147       : memmgr_(0, kFrontbufferLimitForTest) {
148     memmgr_.TestingDisableScheduleManage();
149   }
150
151   void SetUp() override {}
152
153   static int32 GenerateUniqueSurfaceId() {
154     static int32 surface_id_ = 1;
155     return surface_id_++;
156   }
157
158   bool IsAllocationForegroundForSurfaceYes(
159       const MemoryAllocation& alloc) {
160     return true;
161   }
162   bool IsAllocationBackgroundForSurfaceYes(
163       const MemoryAllocation& alloc) {
164     return true;
165   }
166   bool IsAllocationHibernatedForSurfaceYes(
167       const MemoryAllocation& alloc) {
168     return true;
169   }
170   bool IsAllocationForegroundForSurfaceNo(
171       const MemoryAllocation& alloc) {
172     return alloc.bytes_limit_when_visible != 0;
173   }
174   bool IsAllocationBackgroundForSurfaceNo(
175       const MemoryAllocation& alloc) {
176     return alloc.bytes_limit_when_visible != 0;
177   }
178   bool IsAllocationHibernatedForSurfaceNo(
179       const MemoryAllocation& alloc) {
180     return alloc.bytes_limit_when_visible == 0;
181   }
182
183   void Manage() {
184     ClientAssignmentCollector::ClearAllStats();
185     memmgr_.Manage();
186   }
187
188   GpuMemoryManager memmgr_;
189 };
190
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);
200
201   Manage();
202   EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub1.allocation_));
203   EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2.allocation_));
204
205   // Test stubs without surface, with share group of 1 stub.
206   FakeClient stub3(&memmgr_, &stub1), stub4(&memmgr_, &stub2);
207
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_));
213
214   // Test stub without surface, with share group of multiple stubs.
215   FakeClient stub5(&memmgr_ , &stub2);
216
217   Manage();
218   EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub4.allocation_));
219 }
220
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);
229
230   FakeClient stub3(&memmgr_, &stub1), stub4(&memmgr_, &stub2);
231   FakeClient stub5(&memmgr_ , &stub2);
232
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_));
239
240   stub1.SetVisible(false);
241   stub2.SetVisible(true);
242
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_));
249 }
250
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);
259
260   FakeClient stub5(&memmgr_ , &stub1), stub6(&memmgr_ , &stub2);
261   FakeClient stub7(&memmgr_ , &stub2);
262
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_));
271 }
272
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);
285
286   FakeClient stub5(&memmgr_ , &stub1), stub6(&memmgr_ , &stub4);
287   FakeClient stub7(&memmgr_ , &stub1);
288
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_));
297 }
298
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);
307
308   FakeClient stub5(&memmgr_ , &stub3), stub6(&memmgr_ , &stub4);
309   FakeClient stub7(&memmgr_ , &stub3);
310
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);
316
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_));
325
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);
331
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_));
340 }
341
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);
352
353   FakeClient stub3(&memmgr_, &stub2), stub4(&memmgr_, &stub2);
354
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_));
365
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_));
372
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_));
379
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_));
390
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_));
401 }
402
403 }  // namespace content