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
13using gpu::MemoryAllocation;
14using gpu::ManagedMemoryStats;
15
16#if defined(COMPILER_GCC)
17namespace BASE_HASH_NAMESPACE {
18template<>
19struct hash<content::GpuMemoryManagerClient*> {
20  uint64 operator()(content::GpuMemoryManagerClient* ptr) const {
21    return hash<uint64>()(reinterpret_cast<uint64>(ptr));
22  }
23};
24}  // namespace BASE_HASH_NAMESPACE
25#endif  // COMPILER
26
27class FakeMemoryTracker : public gpu::gles2::MemoryTracker {
28 public:
29  virtual void TrackMemoryAllocatedChange(
30      size_t /* old_size */,
31      size_t /* new_size */,
32      gpu::gles2::MemoryTracker::Pool /* pool */) OVERRIDE {
33  }
34  virtual bool EnsureGPUMemoryAvailable(size_t /* size_needed */) OVERRIDE {
35    return true;
36  }
37 private:
38  virtual ~FakeMemoryTracker() {
39  }
40};
41
42namespace content {
43
44// This class is used to collect all stub assignments during a
45// Manage() call.
46class ClientAssignmentCollector {
47 public:
48  struct ClientMemoryStat {
49    MemoryAllocation allocation;
50  };
51  typedef base::hash_map<GpuMemoryManagerClient*, ClientMemoryStat>
52      ClientMemoryStatMap;
53
54  static const ClientMemoryStatMap& GetClientStatsForLastManage() {
55    return client_memory_stats_for_last_manage_;
56  }
57  static void ClearAllStats() {
58    client_memory_stats_for_last_manage_.clear();
59  }
60  static void AddClientStat(GpuMemoryManagerClient* client,
61                          const MemoryAllocation& allocation) {
62    DCHECK(!client_memory_stats_for_last_manage_.count(client));
63    client_memory_stats_for_last_manage_[client].allocation = allocation;
64  }
65
66 private:
67  static ClientMemoryStatMap client_memory_stats_for_last_manage_;
68};
69
70ClientAssignmentCollector::ClientMemoryStatMap
71    ClientAssignmentCollector::client_memory_stats_for_last_manage_;
72
73class FakeClient : public GpuMemoryManagerClient {
74 public:
75  GpuMemoryManager* memmgr_;
76  bool suggest_have_frontbuffer_;
77  MemoryAllocation allocation_;
78  uint64 total_gpu_memory_;
79  gfx::Size surface_size_;
80  GpuMemoryManagerClient* share_group_;
81  scoped_refptr<gpu::gles2::MemoryTracker> memory_tracker_;
82  scoped_ptr<GpuMemoryTrackingGroup> tracking_group_;
83  scoped_ptr<GpuMemoryManagerClientState> client_state_;
84
85  // This will create a client with no surface
86  FakeClient(GpuMemoryManager* memmgr, GpuMemoryManagerClient* share_group)
87      : memmgr_(memmgr),
88        suggest_have_frontbuffer_(false),
89        total_gpu_memory_(0),
90        share_group_(share_group),
91        memory_tracker_(NULL) {
92    if (!share_group_) {
93      memory_tracker_ = new FakeMemoryTracker();
94      tracking_group_.reset(
95          memmgr_->CreateTrackingGroup(0, memory_tracker_.get()));
96    }
97    client_state_.reset(memmgr_->CreateClientState(this, false, true));
98  }
99
100  // This will create a client with a surface
101  FakeClient(GpuMemoryManager* memmgr, int32 surface_id, bool visible)
102      : memmgr_(memmgr),
103        suggest_have_frontbuffer_(false),
104        total_gpu_memory_(0),
105        share_group_(NULL),
106        memory_tracker_(NULL) {
107    memory_tracker_ = new FakeMemoryTracker();
108    tracking_group_.reset(
109        memmgr_->CreateTrackingGroup(0, memory_tracker_.get()));
110    client_state_.reset(
111        memmgr_->CreateClientState(this, surface_id != 0, visible));
112  }
113
114  virtual ~FakeClient() {
115    client_state_.reset();
116    tracking_group_.reset();
117    memory_tracker_ = NULL;
118  }
119
120  virtual void SetMemoryAllocation(const MemoryAllocation& alloc) OVERRIDE {
121    allocation_ = alloc;
122    ClientAssignmentCollector::AddClientStat(this, alloc);
123  }
124
125  virtual void SuggestHaveFrontBuffer(bool suggest_have_frontbuffer) OVERRIDE {
126    suggest_have_frontbuffer_ = suggest_have_frontbuffer;
127  }
128
129  virtual bool GetTotalGpuMemory(uint64* bytes) OVERRIDE {
130    if (total_gpu_memory_) {
131      *bytes = total_gpu_memory_;
132      return true;
133    }
134    return false;
135  }
136  void SetTotalGpuMemory(uint64 bytes) { total_gpu_memory_ = bytes; }
137
138  virtual gpu::gles2::MemoryTracker* GetMemoryTracker() const OVERRIDE {
139    if (share_group_)
140      return share_group_->GetMemoryTracker();
141    return memory_tracker_.get();
142  }
143
144  virtual gfx::Size GetSurfaceSize() const OVERRIDE {
145    return surface_size_;
146  }
147  void SetSurfaceSize(gfx::Size size) { surface_size_ = size; }
148
149  void SetVisible(bool visible) {
150    client_state_->SetVisible(visible);
151  }
152
153  void SetManagedMemoryStats(const ManagedMemoryStats& stats) {
154    client_state_->SetManagedMemoryStats(stats);
155  }
156
157  uint64 BytesWhenVisible() const {
158    return allocation_.bytes_limit_when_visible;
159  }
160};
161
162class GpuMemoryManagerTest : public testing::Test {
163 protected:
164  static const uint64 kFrontbufferLimitForTest = 3;
165
166  GpuMemoryManagerTest()
167      : memmgr_(0, kFrontbufferLimitForTest) {
168    memmgr_.TestingDisableScheduleManage();
169  }
170
171  virtual void SetUp() {
172  }
173
174  static int32 GenerateUniqueSurfaceId() {
175    static int32 surface_id_ = 1;
176    return surface_id_++;
177  }
178
179  bool IsAllocationForegroundForSurfaceYes(
180      const MemoryAllocation& alloc) {
181    return true;
182  }
183  bool IsAllocationBackgroundForSurfaceYes(
184      const MemoryAllocation& alloc) {
185    return true;
186  }
187  bool IsAllocationHibernatedForSurfaceYes(
188      const MemoryAllocation& alloc) {
189    return true;
190  }
191  bool IsAllocationForegroundForSurfaceNo(
192      const MemoryAllocation& alloc) {
193    return alloc.bytes_limit_when_visible ==
194               GetMinimumClientAllocation();
195  }
196  bool IsAllocationBackgroundForSurfaceNo(
197      const MemoryAllocation& alloc) {
198    return alloc.bytes_limit_when_visible ==
199               GetMinimumClientAllocation();
200  }
201  bool IsAllocationHibernatedForSurfaceNo(
202      const MemoryAllocation& alloc) {
203    return alloc.bytes_limit_when_visible == 0;
204  }
205
206  void Manage() {
207    ClientAssignmentCollector::ClearAllStats();
208    memmgr_.Manage();
209  }
210
211  uint64 CalcAvailableFromGpuTotal(uint64 bytes) {
212    return GpuMemoryManager::CalcAvailableFromGpuTotal(bytes);
213  }
214
215  uint64 CalcAvailableClamped(uint64 bytes) {
216    bytes = std::max(bytes, memmgr_.GetDefaultAvailableGpuMemory());
217    bytes = std::min(bytes, memmgr_.GetMaximumTotalGpuMemory());
218    return bytes;
219  }
220
221  uint64 GetAvailableGpuMemory() {
222    return memmgr_.GetAvailableGpuMemory();
223  }
224
225  uint64 GetMaximumClientAllocation() {
226    return memmgr_.GetMaximumClientAllocation();
227  }
228
229  uint64 GetMinimumClientAllocation() {
230    return memmgr_.GetMinimumClientAllocation();
231  }
232
233  void SetClientStats(
234      FakeClient* client,
235      uint64 required,
236      uint64 nicetohave) {
237    client->SetManagedMemoryStats(
238        ManagedMemoryStats(required, nicetohave, 0, false));
239  }
240
241  GpuMemoryManager memmgr_;
242};
243
244// Test GpuMemoryManager::Manage basic functionality.
245// Expect memory allocation to set suggest_have_frontbuffer/backbuffer
246// according to visibility and last used time for stubs with surface.
247// Expect memory allocation to be shared according to share groups for stubs
248// without a surface.
249TEST_F(GpuMemoryManagerTest, TestManageBasicFunctionality) {
250  // Test stubs with surface.
251  FakeClient stub1(&memmgr_, GenerateUniqueSurfaceId(), true),
252             stub2(&memmgr_, GenerateUniqueSurfaceId(), false);
253
254  Manage();
255  EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub1.allocation_));
256  EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2.allocation_));
257
258  // Test stubs without surface, with share group of 1 stub.
259  FakeClient stub3(&memmgr_, &stub1), stub4(&memmgr_, &stub2);
260
261  Manage();
262  EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub1.allocation_));
263  EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2.allocation_));
264  EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub3.allocation_));
265  EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub4.allocation_));
266
267  // Test stub without surface, with share group of multiple stubs.
268  FakeClient stub5(&memmgr_ , &stub2);
269
270  Manage();
271  EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub4.allocation_));
272}
273
274// Test GpuMemoryManager::Manage functionality: changing visibility.
275// Expect memory allocation to set suggest_have_frontbuffer/backbuffer
276// according to visibility and last used time for stubs with surface.
277// Expect memory allocation to be shared according to share groups for stubs
278// without a surface.
279TEST_F(GpuMemoryManagerTest, TestManageChangingVisibility) {
280  FakeClient stub1(&memmgr_, GenerateUniqueSurfaceId(), true),
281             stub2(&memmgr_, GenerateUniqueSurfaceId(), false);
282
283  FakeClient stub3(&memmgr_, &stub1), stub4(&memmgr_, &stub2);
284  FakeClient stub5(&memmgr_ , &stub2);
285
286  Manage();
287  EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub1.allocation_));
288  EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2.allocation_));
289  EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub3.allocation_));
290  EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub4.allocation_));
291  EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub5.allocation_));
292
293  stub1.SetVisible(false);
294  stub2.SetVisible(true);
295
296  Manage();
297  EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub1.allocation_));
298  EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub2.allocation_));
299  EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub3.allocation_));
300  EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub4.allocation_));
301  EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub5.allocation_));
302}
303
304// Test GpuMemoryManager::Manage functionality: Test more than threshold number
305// of visible stubs.
306// Expect all allocations to continue to have frontbuffer.
307TEST_F(GpuMemoryManagerTest, TestManageManyVisibleStubs) {
308  FakeClient stub1(&memmgr_, GenerateUniqueSurfaceId(), true),
309             stub2(&memmgr_, GenerateUniqueSurfaceId(), true),
310             stub3(&memmgr_, GenerateUniqueSurfaceId(), true),
311             stub4(&memmgr_, GenerateUniqueSurfaceId(), true);
312
313  FakeClient stub5(&memmgr_ , &stub1), stub6(&memmgr_ , &stub2);
314  FakeClient stub7(&memmgr_ , &stub2);
315
316  Manage();
317  EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub1.allocation_));
318  EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub2.allocation_));
319  EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub3.allocation_));
320  EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub4.allocation_));
321  EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub5.allocation_));
322  EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub6.allocation_));
323  EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub7.allocation_));
324}
325
326// Test GpuMemoryManager::Manage functionality: Test more than threshold number
327// of not visible stubs.
328// Expect the stubs surpassing the threshold to not have a backbuffer.
329TEST_F(GpuMemoryManagerTest, TestManageManyNotVisibleStubs) {
330  FakeClient stub1(&memmgr_, GenerateUniqueSurfaceId(), true),
331             stub2(&memmgr_, GenerateUniqueSurfaceId(), true),
332             stub3(&memmgr_, GenerateUniqueSurfaceId(), true),
333             stub4(&memmgr_, GenerateUniqueSurfaceId(), true);
334  stub4.SetVisible(false);
335  stub3.SetVisible(false);
336  stub2.SetVisible(false);
337  stub1.SetVisible(false);
338
339  FakeClient stub5(&memmgr_ , &stub1), stub6(&memmgr_ , &stub4);
340  FakeClient stub7(&memmgr_ , &stub1);
341
342  Manage();
343  EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub1.allocation_));
344  EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2.allocation_));
345  EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub3.allocation_));
346  EXPECT_TRUE(IsAllocationHibernatedForSurfaceYes(stub4.allocation_));
347  EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub5.allocation_));
348  EXPECT_TRUE(IsAllocationHibernatedForSurfaceNo(stub6.allocation_));
349  EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub7.allocation_));
350}
351
352// Test GpuMemoryManager::Manage functionality: Test changing the last used
353// time of stubs when doing so causes change in which stubs surpass threshold.
354// Expect frontbuffer to be dropped for the older stub.
355TEST_F(GpuMemoryManagerTest, TestManageChangingLastUsedTime) {
356  FakeClient stub1(&memmgr_, GenerateUniqueSurfaceId(), true),
357             stub2(&memmgr_, GenerateUniqueSurfaceId(), true),
358             stub3(&memmgr_, GenerateUniqueSurfaceId(), true),
359             stub4(&memmgr_, GenerateUniqueSurfaceId(), true);
360
361  FakeClient stub5(&memmgr_ , &stub3), stub6(&memmgr_ , &stub4);
362  FakeClient stub7(&memmgr_ , &stub3);
363
364  // Make stub4 be the least-recently-used client
365  stub4.SetVisible(false);
366  stub3.SetVisible(false);
367  stub2.SetVisible(false);
368  stub1.SetVisible(false);
369
370  Manage();
371  EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub1.allocation_));
372  EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2.allocation_));
373  EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub3.allocation_));
374  EXPECT_TRUE(IsAllocationHibernatedForSurfaceYes(stub4.allocation_));
375  EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub5.allocation_));
376  EXPECT_TRUE(IsAllocationHibernatedForSurfaceNo(stub6.allocation_));
377  EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub7.allocation_));
378
379  // Make stub3 become the least-recently-used client.
380  stub2.SetVisible(true);
381  stub2.SetVisible(false);
382  stub4.SetVisible(true);
383  stub4.SetVisible(false);
384
385  Manage();
386  EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub1.allocation_));
387  EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2.allocation_));
388  EXPECT_TRUE(IsAllocationHibernatedForSurfaceYes(stub3.allocation_));
389  EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub4.allocation_));
390  EXPECT_TRUE(IsAllocationHibernatedForSurfaceNo(stub5.allocation_));
391  EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub6.allocation_));
392  EXPECT_TRUE(IsAllocationHibernatedForSurfaceNo(stub7.allocation_));
393}
394
395// Test GpuMemoryManager::Manage functionality: Test changing importance of
396// enough stubs so that every stub in share group crosses threshold.
397// Expect memory allocation of the stubs without surface to share memory
398// allocation with the most visible stub in share group.
399TEST_F(GpuMemoryManagerTest, TestManageChangingImportanceShareGroup) {
400  FakeClient stub_ignore_a(&memmgr_, GenerateUniqueSurfaceId(), true),
401             stub_ignore_b(&memmgr_, GenerateUniqueSurfaceId(), false),
402             stub_ignore_c(&memmgr_, GenerateUniqueSurfaceId(), false);
403  FakeClient stub1(&memmgr_, GenerateUniqueSurfaceId(), false),
404             stub2(&memmgr_, GenerateUniqueSurfaceId(), false);
405
406  FakeClient stub3(&memmgr_, &stub2), stub4(&memmgr_, &stub2);
407
408  // stub1 and stub2 keep their non-hibernated state because they're
409  // either visible or the 2 most recently used clients (through the
410  // first three checks).
411  stub1.SetVisible(true);
412  stub2.SetVisible(true);
413  Manage();
414  EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub1.allocation_));
415  EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub2.allocation_));
416  EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub3.allocation_));
417  EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub4.allocation_));
418
419  stub1.SetVisible(false);
420  Manage();
421  EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub1.allocation_));
422  EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub2.allocation_));
423  EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub3.allocation_));
424  EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub4.allocation_));
425
426  stub2.SetVisible(false);
427  Manage();
428  EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub1.allocation_));
429  EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2.allocation_));
430  EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub3.allocation_));
431  EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub4.allocation_));
432
433  // stub_ignore_b will cause stub1 to become hibernated (because
434  // stub_ignore_a, stub_ignore_b, and stub2 are all non-hibernated and more
435  // important).
436  stub_ignore_b.SetVisible(true);
437  stub_ignore_b.SetVisible(false);
438  Manage();
439  EXPECT_TRUE(IsAllocationHibernatedForSurfaceYes(stub1.allocation_));
440  EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2.allocation_));
441  EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub3.allocation_));
442  EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub4.allocation_));
443
444  // stub_ignore_c will cause stub2 to become hibernated (because
445  // stub_ignore_a, stub_ignore_b, and stub_ignore_c are all non-hibernated
446  // and more important).
447  stub_ignore_c.SetVisible(true);
448  stub_ignore_c.SetVisible(false);
449  Manage();
450  EXPECT_TRUE(IsAllocationHibernatedForSurfaceYes(stub1.allocation_));
451  EXPECT_TRUE(IsAllocationHibernatedForSurfaceYes(stub2.allocation_));
452  EXPECT_TRUE(IsAllocationHibernatedForSurfaceNo(stub3.allocation_));
453  EXPECT_TRUE(IsAllocationHibernatedForSurfaceNo(stub4.allocation_));
454}
455
456// Test GpuMemoryManager::UpdateAvailableGpuMemory functionality
457TEST_F(GpuMemoryManagerTest, TestUpdateAvailableGpuMemory) {
458  FakeClient stub1(&memmgr_, GenerateUniqueSurfaceId(), true),
459             stub2(&memmgr_, GenerateUniqueSurfaceId(), false),
460             stub3(&memmgr_, GenerateUniqueSurfaceId(), true),
461             stub4(&memmgr_, GenerateUniqueSurfaceId(), false);
462  // We take the lowest GPU's total memory as the limit
463  uint64 expected = 400 * 1024 * 1024;
464  stub1.SetTotalGpuMemory(expected); // GPU Memory
465  stub2.SetTotalGpuMemory(expected - 1024 * 1024); // Smaller but not visible.
466  stub3.SetTotalGpuMemory(expected + 1024 * 1024); // Visible but larger.
467  stub4.SetTotalGpuMemory(expected + 1024 * 1024); // Not visible and larger.
468  Manage();
469  uint64 bytes_expected = CalcAvailableFromGpuTotal(expected);
470  EXPECT_EQ(GetAvailableGpuMemory(), CalcAvailableClamped(bytes_expected));
471}
472
473// Test GpuMemoryManager Stub Memory Stats functionality:
474// Creates various surface/non-surface stubs and switches stub visibility and
475// tests to see that stats data structure values are correct.
476TEST_F(GpuMemoryManagerTest, StubMemoryStatsForLastManageTests) {
477  ClientAssignmentCollector::ClientMemoryStatMap stats;
478
479  Manage();
480  stats = ClientAssignmentCollector::GetClientStatsForLastManage();
481  EXPECT_EQ(stats.size(), 0ul);
482
483  FakeClient stub1(&memmgr_, GenerateUniqueSurfaceId(), true);
484  Manage();
485  stats = ClientAssignmentCollector::GetClientStatsForLastManage();
486  uint64 stub1allocation1 =
487      stats[&stub1].allocation.bytes_limit_when_visible;
488
489  EXPECT_EQ(stats.size(), 1ul);
490  EXPECT_GT(stub1allocation1, 0ul);
491
492  FakeClient stub2(&memmgr_, &stub1);
493  Manage();
494  stats = ClientAssignmentCollector::GetClientStatsForLastManage();
495  EXPECT_EQ(stats.count(&stub1), 1ul);
496  uint64 stub1allocation2 =
497      stats[&stub1].allocation.bytes_limit_when_visible;
498  EXPECT_EQ(stats.count(&stub2), 1ul);
499  uint64 stub2allocation2 =
500      stats[&stub2].allocation.bytes_limit_when_visible;
501
502  EXPECT_EQ(stats.size(), 2ul);
503  EXPECT_GT(stub1allocation2, 0ul);
504  EXPECT_GT(stub2allocation2, 0ul);
505  if (stub1allocation2 != GetMaximumClientAllocation())
506    EXPECT_LT(stub1allocation2, stub1allocation1);
507
508  FakeClient stub3(&memmgr_, GenerateUniqueSurfaceId(), true);
509  Manage();
510  stats = ClientAssignmentCollector::GetClientStatsForLastManage();
511  uint64 stub1allocation3 =
512      stats[&stub1].allocation.bytes_limit_when_visible;
513  uint64 stub2allocation3 =
514      stats[&stub2].allocation.bytes_limit_when_visible;
515  uint64 stub3allocation3 =
516      stats[&stub3].allocation.bytes_limit_when_visible;
517
518  EXPECT_EQ(stats.size(), 3ul);
519  EXPECT_GT(stub1allocation3, 0ul);
520  EXPECT_GT(stub2allocation3, 0ul);
521  EXPECT_GT(stub3allocation3, 0ul);
522  if (stub1allocation3 != GetMaximumClientAllocation())
523    EXPECT_LT(stub1allocation3, stub1allocation2);
524
525  stub1.SetVisible(false);
526
527  Manage();
528  stats = ClientAssignmentCollector::GetClientStatsForLastManage();
529  uint64 stub1allocation4 =
530      stats[&stub1].allocation.bytes_limit_when_visible;
531  uint64 stub2allocation4 =
532      stats[&stub2].allocation.bytes_limit_when_visible;
533  uint64 stub3allocation4 =
534      stats[&stub3].allocation.bytes_limit_when_visible;
535
536  EXPECT_EQ(stats.size(), 3ul);
537  EXPECT_GT(stub1allocation4, 0ul);
538  EXPECT_GE(stub2allocation4, 0ul);
539  EXPECT_GT(stub3allocation4, 0ul);
540  if (stub3allocation3 != GetMaximumClientAllocation())
541    EXPECT_GT(stub3allocation4, stub3allocation3);
542}
543
544// Test tracking of unmanaged (e.g, WebGL) memory.
545TEST_F(GpuMemoryManagerTest, UnmanagedTracking) {
546  // Set memory manager constants for this test
547  memmgr_.TestingSetAvailableGpuMemory(64);
548  memmgr_.TestingSetMinimumClientAllocation(8);
549  memmgr_.TestingSetUnmanagedLimitStep(16);
550
551  FakeClient stub1(&memmgr_, GenerateUniqueSurfaceId(), true);
552
553  // Expect that the one stub get its nicetohave level.
554  SetClientStats(&stub1, 16, 32);
555  Manage();
556  EXPECT_GE(stub1.BytesWhenVisible(), 32u);
557
558  // Now allocate some unmanaged memory and make sure the amount
559  // goes down.
560  memmgr_.TrackMemoryAllocatedChange(
561      stub1.tracking_group_.get(),
562      0,
563      48,
564      gpu::gles2::MemoryTracker::kUnmanaged);
565  Manage();
566  EXPECT_LT(stub1.BytesWhenVisible(), 24u);
567
568  // Now allocate the entire FB worth of unmanaged memory, and
569  // make sure that we stay stuck at the minimum tab allocation.
570  memmgr_.TrackMemoryAllocatedChange(
571      stub1.tracking_group_.get(),
572      48,
573      64,
574      gpu::gles2::MemoryTracker::kUnmanaged);
575  Manage();
576  EXPECT_EQ(stub1.BytesWhenVisible(), 8u);
577
578  // Far-oversubscribe the entire FB, and make sure we stay at
579  // the minimum allocation, and don't blow up.
580  memmgr_.TrackMemoryAllocatedChange(
581      stub1.tracking_group_.get(),
582      64,
583      999,
584      gpu::gles2::MemoryTracker::kUnmanaged);
585  Manage();
586  EXPECT_EQ(stub1.BytesWhenVisible(), 8u);
587
588  // Delete all tracked memory so we don't hit leak checks.
589  memmgr_.TrackMemoryAllocatedChange(
590      stub1.tracking_group_.get(),
591      999,
592      0,
593      gpu::gles2::MemoryTracker::kUnmanaged);
594}
595
596// Test the default allocation levels are used.
597TEST_F(GpuMemoryManagerTest, DefaultAllocation) {
598  // Set memory manager constants for this test
599  memmgr_.TestingSetAvailableGpuMemory(64);
600  memmgr_.TestingSetMinimumClientAllocation(8);
601  memmgr_.TestingSetDefaultClientAllocation(16);
602
603  FakeClient stub1(&memmgr_, GenerateUniqueSurfaceId(), true);
604
605  // Expect that a client which has not sent stats receive at
606  // least the default allocation.
607  Manage();
608  EXPECT_GE(stub1.BytesWhenVisible(),
609            memmgr_.GetDefaultClientAllocation());
610}
611
612}  // namespace content
613