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_allocation.h" 6 #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 "ui/gfx/size_conversions.h" 10 11 #include "testing/gtest/include/gtest/gtest.h" 12 13 #if defined(COMPILER_GCC) 14 namespace BASE_HASH_NAMESPACE { 15 template<> 16 struct hash<content::GpuMemoryManagerClient*> { 17 uint64 operator()(content::GpuMemoryManagerClient* ptr) const { 18 return hash<uint64>()(reinterpret_cast<uint64>(ptr)); 19 } 20 }; 21 } // namespace BASE_HASH_NAMESPACE 22 #endif // COMPILER 23 24 class FakeMemoryTracker : public gpu::gles2::MemoryTracker { 25 public: 26 virtual void TrackMemoryAllocatedChange( 27 size_t /* old_size */, 28 size_t /* new_size */, 29 gpu::gles2::MemoryTracker::Pool /* pool */) OVERRIDE { 30 } 31 virtual bool EnsureGPUMemoryAvailable(size_t /* size_needed */) OVERRIDE { 32 return true; 33 } 34 private: 35 virtual ~FakeMemoryTracker() { 36 } 37 }; 38 39 namespace content { 40 41 // This class is used to collect all stub assignments during a 42 // Manage() call. 43 class ClientAssignmentCollector { 44 public: 45 struct ClientMemoryStat { 46 GpuMemoryAllocation allocation; 47 }; 48 typedef base::hash_map<GpuMemoryManagerClient*, ClientMemoryStat> 49 ClientMemoryStatMap; 50 51 static const ClientMemoryStatMap& GetClientStatsForLastManage() { 52 return client_memory_stats_for_last_manage_; 53 } 54 static void ClearAllStats() { 55 client_memory_stats_for_last_manage_.clear(); 56 } 57 static void AddClientStat(GpuMemoryManagerClient* client, 58 const GpuMemoryAllocation& allocation) { 59 DCHECK(!client_memory_stats_for_last_manage_.count(client)); 60 client_memory_stats_for_last_manage_[client].allocation = allocation; 61 } 62 63 private: 64 static ClientMemoryStatMap client_memory_stats_for_last_manage_; 65 }; 66 67 ClientAssignmentCollector::ClientMemoryStatMap 68 ClientAssignmentCollector::client_memory_stats_for_last_manage_; 69 70 class FakeClient : public GpuMemoryManagerClient { 71 public: 72 GpuMemoryManager* memmgr_; 73 GpuMemoryAllocation allocation_; 74 uint64 total_gpu_memory_; 75 gfx::Size surface_size_; 76 GpuMemoryManagerClient* share_group_; 77 scoped_refptr<gpu::gles2::MemoryTracker> memory_tracker_; 78 scoped_ptr<GpuMemoryTrackingGroup> tracking_group_; 79 scoped_ptr<GpuMemoryManagerClientState> client_state_; 80 81 // This will create a client with no surface 82 FakeClient(GpuMemoryManager* memmgr, GpuMemoryManagerClient* share_group) 83 : memmgr_(memmgr), 84 total_gpu_memory_(0), 85 share_group_(share_group), 86 memory_tracker_(NULL) { 87 if (!share_group_) { 88 memory_tracker_ = new FakeMemoryTracker(); 89 tracking_group_.reset( 90 memmgr_->CreateTrackingGroup(0, memory_tracker_.get())); 91 } 92 client_state_.reset(memmgr_->CreateClientState(this, false, true)); 93 } 94 95 // This will create a client with a surface 96 FakeClient(GpuMemoryManager* memmgr, int32 surface_id, bool visible) 97 : memmgr_(memmgr), 98 total_gpu_memory_(0), 99 share_group_(NULL), 100 memory_tracker_(NULL) { 101 memory_tracker_ = new FakeMemoryTracker(); 102 tracking_group_.reset( 103 memmgr_->CreateTrackingGroup(0, memory_tracker_.get())); 104 client_state_.reset( 105 memmgr_->CreateClientState(this, surface_id != 0, visible)); 106 } 107 108 virtual ~FakeClient() { 109 client_state_.reset(); 110 tracking_group_.reset(); 111 memory_tracker_ = NULL; 112 } 113 114 virtual void SetMemoryAllocation(const GpuMemoryAllocation& alloc) OVERRIDE { 115 allocation_ = alloc; 116 ClientAssignmentCollector::AddClientStat(this, alloc); 117 } 118 119 virtual bool GetTotalGpuMemory(uint64* bytes) OVERRIDE { 120 if (total_gpu_memory_) { 121 *bytes = total_gpu_memory_; 122 return true; 123 } 124 return false; 125 } 126 void SetTotalGpuMemory(uint64 bytes) { total_gpu_memory_ = bytes; } 127 128 virtual gpu::gles2::MemoryTracker* GetMemoryTracker() const OVERRIDE { 129 if (share_group_) 130 return share_group_->GetMemoryTracker(); 131 return memory_tracker_.get(); 132 } 133 134 virtual gfx::Size GetSurfaceSize() const OVERRIDE { 135 return surface_size_; 136 } 137 void SetSurfaceSize(gfx::Size size) { surface_size_ = size; } 138 139 void SetVisible(bool visible) { 140 client_state_->SetVisible(visible); 141 } 142 143 void SetManagedMemoryStats(const GpuManagedMemoryStats& stats) { 144 client_state_->SetManagedMemoryStats(stats); 145 } 146 147 uint64 BytesWhenVisible() const { 148 return allocation_.renderer_allocation.bytes_limit_when_visible; 149 } 150 151 uint64 BytesWhenNotVisible() const { 152 return allocation_.renderer_allocation.bytes_limit_when_not_visible; 153 } 154 }; 155 156 class GpuMemoryManagerTest : public testing::Test { 157 protected: 158 static const uint64 kFrontbufferLimitForTest = 3; 159 160 GpuMemoryManagerTest() 161 : memmgr_(0, kFrontbufferLimitForTest) { 162 memmgr_.TestingDisableScheduleManage(); 163 } 164 165 virtual void SetUp() { 166 } 167 168 static int32 GenerateUniqueSurfaceId() { 169 static int32 surface_id_ = 1; 170 return surface_id_++; 171 } 172 173 bool IsAllocationForegroundForSurfaceYes( 174 const GpuMemoryAllocation& alloc) { 175 return alloc.browser_allocation.suggest_have_frontbuffer && 176 !alloc.renderer_allocation.have_backbuffer_when_not_visible; 177 } 178 bool IsAllocationBackgroundForSurfaceYes( 179 const GpuMemoryAllocation& alloc) { 180 return alloc.browser_allocation.suggest_have_frontbuffer && 181 !alloc.renderer_allocation.have_backbuffer_when_not_visible; 182 } 183 bool IsAllocationHibernatedForSurfaceYes( 184 const GpuMemoryAllocation& alloc) { 185 return !alloc.browser_allocation.suggest_have_frontbuffer && 186 !alloc.renderer_allocation.have_backbuffer_when_not_visible; 187 } 188 bool IsAllocationForegroundForSurfaceNo( 189 const GpuMemoryAllocation& alloc) { 190 return !alloc.browser_allocation.suggest_have_frontbuffer && 191 !alloc.renderer_allocation.have_backbuffer_when_not_visible && 192 alloc.renderer_allocation.bytes_limit_when_visible == 193 GetMinimumClientAllocation(); 194 } 195 bool IsAllocationBackgroundForSurfaceNo( 196 const GpuMemoryAllocation& alloc) { 197 return !alloc.browser_allocation.suggest_have_frontbuffer && 198 !alloc.renderer_allocation.have_backbuffer_when_not_visible && 199 alloc.renderer_allocation.bytes_limit_when_visible == 200 GetMinimumClientAllocation(); 201 } 202 bool IsAllocationHibernatedForSurfaceNo( 203 const GpuMemoryAllocation& alloc) { 204 return !alloc.browser_allocation.suggest_have_frontbuffer && 205 !alloc.renderer_allocation.have_backbuffer_when_not_visible && 206 alloc.renderer_allocation.bytes_limit_when_visible == 0; 207 } 208 209 void Manage() { 210 ClientAssignmentCollector::ClearAllStats(); 211 memmgr_.Manage(); 212 } 213 214 uint64 CalcAvailableFromGpuTotal(uint64 bytes) { 215 return GpuMemoryManager::CalcAvailableFromGpuTotal(bytes); 216 } 217 218 uint64 CalcAvailableClamped(uint64 bytes) { 219 bytes = std::max(bytes, memmgr_.GetDefaultAvailableGpuMemory()); 220 bytes = std::min(bytes, memmgr_.GetMaximumTotalGpuMemory()); 221 return bytes; 222 } 223 224 uint64 GetAvailableGpuMemory() { 225 return memmgr_.GetAvailableGpuMemory(); 226 } 227 228 uint64 GetMaximumClientAllocation() { 229 return memmgr_.GetMaximumClientAllocation(); 230 } 231 232 uint64 GetMinimumClientAllocation() { 233 return memmgr_.GetMinimumClientAllocation(); 234 } 235 236 void SetClientStats( 237 FakeClient* client, 238 uint64 required, 239 uint64 nicetohave) { 240 client->SetManagedMemoryStats( 241 GpuManagedMemoryStats(required, nicetohave, 0, false)); 242 } 243 244 GpuMemoryManager memmgr_; 245 }; 246 247 // Test GpuMemoryManager::Manage basic functionality. 248 // Expect memory allocation to set suggest_have_frontbuffer/backbuffer 249 // according to visibility and last used time for stubs with surface. 250 // Expect memory allocation to be shared according to share groups for stubs 251 // without a surface. 252 TEST_F(GpuMemoryManagerTest, TestManageBasicFunctionality) { 253 // Test stubs with surface. 254 FakeClient stub1(&memmgr_, GenerateUniqueSurfaceId(), true), 255 stub2(&memmgr_, GenerateUniqueSurfaceId(), false); 256 257 Manage(); 258 EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub1.allocation_)); 259 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2.allocation_)); 260 261 // Test stubs without surface, with share group of 1 stub. 262 FakeClient stub3(&memmgr_, &stub1), stub4(&memmgr_, &stub2); 263 264 Manage(); 265 EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub1.allocation_)); 266 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2.allocation_)); 267 EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub3.allocation_)); 268 EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub4.allocation_)); 269 270 // Test stub without surface, with share group of multiple stubs. 271 FakeClient stub5(&memmgr_ , &stub2); 272 273 Manage(); 274 EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub4.allocation_)); 275 } 276 277 // Test GpuMemoryManager::Manage functionality: changing visibility. 278 // Expect memory allocation to set suggest_have_frontbuffer/backbuffer 279 // according to visibility and last used time for stubs with surface. 280 // Expect memory allocation to be shared according to share groups for stubs 281 // without a surface. 282 TEST_F(GpuMemoryManagerTest, TestManageChangingVisibility) { 283 FakeClient stub1(&memmgr_, GenerateUniqueSurfaceId(), true), 284 stub2(&memmgr_, GenerateUniqueSurfaceId(), false); 285 286 FakeClient stub3(&memmgr_, &stub1), stub4(&memmgr_, &stub2); 287 FakeClient stub5(&memmgr_ , &stub2); 288 289 Manage(); 290 EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub1.allocation_)); 291 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2.allocation_)); 292 EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub3.allocation_)); 293 EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub4.allocation_)); 294 EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub5.allocation_)); 295 296 stub1.SetVisible(false); 297 stub2.SetVisible(true); 298 299 Manage(); 300 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub1.allocation_)); 301 EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub2.allocation_)); 302 EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub3.allocation_)); 303 EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub4.allocation_)); 304 EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub5.allocation_)); 305 } 306 307 // Test GpuMemoryManager::Manage functionality: Test more than threshold number 308 // of visible stubs. 309 // Expect all allocations to continue to have frontbuffer. 310 TEST_F(GpuMemoryManagerTest, TestManageManyVisibleStubs) { 311 FakeClient stub1(&memmgr_, GenerateUniqueSurfaceId(), true), 312 stub2(&memmgr_, GenerateUniqueSurfaceId(), true), 313 stub3(&memmgr_, GenerateUniqueSurfaceId(), true), 314 stub4(&memmgr_, GenerateUniqueSurfaceId(), true); 315 316 FakeClient stub5(&memmgr_ , &stub1), stub6(&memmgr_ , &stub2); 317 FakeClient stub7(&memmgr_ , &stub2); 318 319 Manage(); 320 EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub1.allocation_)); 321 EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub2.allocation_)); 322 EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub3.allocation_)); 323 EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub4.allocation_)); 324 EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub5.allocation_)); 325 EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub6.allocation_)); 326 EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub7.allocation_)); 327 } 328 329 // Test GpuMemoryManager::Manage functionality: Test more than threshold number 330 // of not visible stubs. 331 // Expect the stubs surpassing the threshold to not have a backbuffer. 332 TEST_F(GpuMemoryManagerTest, TestManageManyNotVisibleStubs) { 333 FakeClient stub1(&memmgr_, GenerateUniqueSurfaceId(), true), 334 stub2(&memmgr_, GenerateUniqueSurfaceId(), true), 335 stub3(&memmgr_, GenerateUniqueSurfaceId(), true), 336 stub4(&memmgr_, GenerateUniqueSurfaceId(), true); 337 stub4.SetVisible(false); 338 stub3.SetVisible(false); 339 stub2.SetVisible(false); 340 stub1.SetVisible(false); 341 342 FakeClient stub5(&memmgr_ , &stub1), stub6(&memmgr_ , &stub4); 343 FakeClient stub7(&memmgr_ , &stub1); 344 345 Manage(); 346 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub1.allocation_)); 347 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2.allocation_)); 348 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub3.allocation_)); 349 EXPECT_TRUE(IsAllocationHibernatedForSurfaceYes(stub4.allocation_)); 350 EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub5.allocation_)); 351 EXPECT_TRUE(IsAllocationHibernatedForSurfaceNo(stub6.allocation_)); 352 EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub7.allocation_)); 353 } 354 355 // Test GpuMemoryManager::Manage functionality: Test changing the last used 356 // time of stubs when doing so causes change in which stubs surpass threshold. 357 // Expect frontbuffer to be dropped for the older stub. 358 TEST_F(GpuMemoryManagerTest, TestManageChangingLastUsedTime) { 359 FakeClient stub1(&memmgr_, GenerateUniqueSurfaceId(), true), 360 stub2(&memmgr_, GenerateUniqueSurfaceId(), true), 361 stub3(&memmgr_, GenerateUniqueSurfaceId(), true), 362 stub4(&memmgr_, GenerateUniqueSurfaceId(), true); 363 364 FakeClient stub5(&memmgr_ , &stub3), stub6(&memmgr_ , &stub4); 365 FakeClient stub7(&memmgr_ , &stub3); 366 367 // Make stub4 be the least-recently-used client 368 stub4.SetVisible(false); 369 stub3.SetVisible(false); 370 stub2.SetVisible(false); 371 stub1.SetVisible(false); 372 373 Manage(); 374 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub1.allocation_)); 375 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2.allocation_)); 376 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub3.allocation_)); 377 EXPECT_TRUE(IsAllocationHibernatedForSurfaceYes(stub4.allocation_)); 378 EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub5.allocation_)); 379 EXPECT_TRUE(IsAllocationHibernatedForSurfaceNo(stub6.allocation_)); 380 EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub7.allocation_)); 381 382 // Make stub3 become the least-recently-used client. 383 stub2.SetVisible(true); 384 stub2.SetVisible(false); 385 stub4.SetVisible(true); 386 stub4.SetVisible(false); 387 388 Manage(); 389 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub1.allocation_)); 390 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2.allocation_)); 391 EXPECT_TRUE(IsAllocationHibernatedForSurfaceYes(stub3.allocation_)); 392 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub4.allocation_)); 393 EXPECT_TRUE(IsAllocationHibernatedForSurfaceNo(stub5.allocation_)); 394 EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub6.allocation_)); 395 EXPECT_TRUE(IsAllocationHibernatedForSurfaceNo(stub7.allocation_)); 396 } 397 398 // Test GpuMemoryManager::Manage functionality: Test changing importance of 399 // enough stubs so that every stub in share group crosses threshold. 400 // Expect memory allocation of the stubs without surface to share memory 401 // allocation with the most visible stub in share group. 402 TEST_F(GpuMemoryManagerTest, TestManageChangingImportanceShareGroup) { 403 FakeClient stub_ignore_a(&memmgr_, GenerateUniqueSurfaceId(), true), 404 stub_ignore_b(&memmgr_, GenerateUniqueSurfaceId(), false), 405 stub_ignore_c(&memmgr_, GenerateUniqueSurfaceId(), false); 406 FakeClient stub1(&memmgr_, GenerateUniqueSurfaceId(), false), 407 stub2(&memmgr_, GenerateUniqueSurfaceId(), false); 408 409 FakeClient stub3(&memmgr_, &stub2), stub4(&memmgr_, &stub2); 410 411 // stub1 and stub2 keep their non-hibernated state because they're 412 // either visible or the 2 most recently used clients (through the 413 // first three checks). 414 stub1.SetVisible(true); 415 stub2.SetVisible(true); 416 Manage(); 417 EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub1.allocation_)); 418 EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub2.allocation_)); 419 EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub3.allocation_)); 420 EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub4.allocation_)); 421 422 stub1.SetVisible(false); 423 Manage(); 424 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub1.allocation_)); 425 EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub2.allocation_)); 426 EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub3.allocation_)); 427 EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub4.allocation_)); 428 429 stub2.SetVisible(false); 430 Manage(); 431 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub1.allocation_)); 432 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2.allocation_)); 433 EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub3.allocation_)); 434 EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub4.allocation_)); 435 436 // stub_ignore_b will cause stub1 to become hibernated (because 437 // stub_ignore_a, stub_ignore_b, and stub2 are all non-hibernated and more 438 // important). 439 stub_ignore_b.SetVisible(true); 440 stub_ignore_b.SetVisible(false); 441 Manage(); 442 EXPECT_TRUE(IsAllocationHibernatedForSurfaceYes(stub1.allocation_)); 443 EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2.allocation_)); 444 EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub3.allocation_)); 445 EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub4.allocation_)); 446 447 // stub_ignore_c will cause stub2 to become hibernated (because 448 // stub_ignore_a, stub_ignore_b, and stub_ignore_c are all non-hibernated 449 // and more important). 450 stub_ignore_c.SetVisible(true); 451 stub_ignore_c.SetVisible(false); 452 Manage(); 453 EXPECT_TRUE(IsAllocationHibernatedForSurfaceYes(stub1.allocation_)); 454 EXPECT_TRUE(IsAllocationHibernatedForSurfaceYes(stub2.allocation_)); 455 EXPECT_TRUE(IsAllocationHibernatedForSurfaceNo(stub3.allocation_)); 456 EXPECT_TRUE(IsAllocationHibernatedForSurfaceNo(stub4.allocation_)); 457 } 458 459 // Test GpuMemoryManager::UpdateAvailableGpuMemory functionality 460 TEST_F(GpuMemoryManagerTest, TestUpdateAvailableGpuMemory) { 461 FakeClient stub1(&memmgr_, GenerateUniqueSurfaceId(), true), 462 stub2(&memmgr_, GenerateUniqueSurfaceId(), false), 463 stub3(&memmgr_, GenerateUniqueSurfaceId(), true), 464 stub4(&memmgr_, GenerateUniqueSurfaceId(), false); 465 // We take the lowest GPU's total memory as the limit 466 uint64 expected = 400 * 1024 * 1024; 467 stub1.SetTotalGpuMemory(expected); // GPU Memory 468 stub2.SetTotalGpuMemory(expected - 1024 * 1024); // Smaller but not visible. 469 stub3.SetTotalGpuMemory(expected + 1024 * 1024); // Visible but larger. 470 stub4.SetTotalGpuMemory(expected + 1024 * 1024); // Not visible and larger. 471 Manage(); 472 uint64 bytes_expected = CalcAvailableFromGpuTotal(expected); 473 EXPECT_EQ(GetAvailableGpuMemory(), CalcAvailableClamped(bytes_expected)); 474 } 475 476 477 // Test GpuMemoryAllocation comparison operators: Iterate over all possible 478 // combinations of gpu_resource_size_in_bytes, suggest_have_backbuffer, and 479 // suggest_have_frontbuffer, and make sure allocations with equal values test 480 // equal and non equal values test not equal. 481 TEST_F(GpuMemoryManagerTest, GpuMemoryAllocationCompareTests) { 482 std::vector<int> gpu_resource_size_in_bytes_values; 483 gpu_resource_size_in_bytes_values.push_back(0); 484 gpu_resource_size_in_bytes_values.push_back(1); 485 gpu_resource_size_in_bytes_values.push_back(12345678); 486 487 std::vector<GpuMemoryAllocation::BufferAllocation> 488 suggested_buffer_allocation_values; 489 suggested_buffer_allocation_values.push_back( 490 GpuMemoryAllocation::kHasFrontbuffer); 491 suggested_buffer_allocation_values.push_back( 492 GpuMemoryAllocation::kHasFrontbuffer); 493 suggested_buffer_allocation_values.push_back( 494 GpuMemoryAllocation::kHasNoFrontbuffer); 495 suggested_buffer_allocation_values.push_back( 496 GpuMemoryAllocation::kHasNoFrontbuffer); 497 498 for (size_t i = 0; i != gpu_resource_size_in_bytes_values.size(); ++i) { 499 for (size_t j = 0; j != suggested_buffer_allocation_values.size(); ++j) { 500 uint64 sz = gpu_resource_size_in_bytes_values[i]; 501 GpuMemoryAllocation::BufferAllocation buffer_allocation = 502 suggested_buffer_allocation_values[j]; 503 GpuMemoryAllocation allocation(sz, buffer_allocation); 504 505 EXPECT_TRUE(allocation.Equals( 506 GpuMemoryAllocation(sz, buffer_allocation))); 507 EXPECT_FALSE(allocation.Equals( 508 GpuMemoryAllocation(sz+1, buffer_allocation))); 509 510 for (size_t k = 0; k != suggested_buffer_allocation_values.size(); ++k) { 511 GpuMemoryAllocation::BufferAllocation buffer_allocation_other = 512 suggested_buffer_allocation_values[k]; 513 if (buffer_allocation == buffer_allocation_other) continue; 514 EXPECT_FALSE(allocation.Equals( 515 GpuMemoryAllocation(sz, buffer_allocation_other))); 516 } 517 } 518 } 519 } 520 521 // Test GpuMemoryManager Stub Memory Stats functionality: 522 // Creates various surface/non-surface stubs and switches stub visibility and 523 // tests to see that stats data structure values are correct. 524 TEST_F(GpuMemoryManagerTest, StubMemoryStatsForLastManageTests) { 525 ClientAssignmentCollector::ClientMemoryStatMap stats; 526 527 Manage(); 528 stats = ClientAssignmentCollector::GetClientStatsForLastManage(); 529 EXPECT_EQ(stats.size(), 0ul); 530 531 FakeClient stub1(&memmgr_, GenerateUniqueSurfaceId(), true); 532 Manage(); 533 stats = ClientAssignmentCollector::GetClientStatsForLastManage(); 534 uint64 stub1allocation1 = 535 stats[&stub1].allocation.renderer_allocation.bytes_limit_when_visible; 536 537 EXPECT_EQ(stats.size(), 1ul); 538 EXPECT_GT(stub1allocation1, 0ul); 539 540 FakeClient stub2(&memmgr_, &stub1); 541 Manage(); 542 stats = ClientAssignmentCollector::GetClientStatsForLastManage(); 543 EXPECT_EQ(stats.count(&stub1), 1ul); 544 uint64 stub1allocation2 = 545 stats[&stub1].allocation.renderer_allocation.bytes_limit_when_visible; 546 EXPECT_EQ(stats.count(&stub2), 1ul); 547 uint64 stub2allocation2 = 548 stats[&stub2].allocation.renderer_allocation.bytes_limit_when_visible; 549 550 EXPECT_EQ(stats.size(), 2ul); 551 EXPECT_GT(stub1allocation2, 0ul); 552 EXPECT_GT(stub2allocation2, 0ul); 553 if (stub1allocation2 != GetMaximumClientAllocation()) 554 EXPECT_LT(stub1allocation2, stub1allocation1); 555 556 FakeClient stub3(&memmgr_, GenerateUniqueSurfaceId(), true); 557 Manage(); 558 stats = ClientAssignmentCollector::GetClientStatsForLastManage(); 559 uint64 stub1allocation3 = 560 stats[&stub1].allocation.renderer_allocation.bytes_limit_when_visible; 561 uint64 stub2allocation3 = 562 stats[&stub2].allocation.renderer_allocation.bytes_limit_when_visible; 563 uint64 stub3allocation3 = 564 stats[&stub3].allocation.renderer_allocation.bytes_limit_when_visible; 565 566 EXPECT_EQ(stats.size(), 3ul); 567 EXPECT_GT(stub1allocation3, 0ul); 568 EXPECT_GT(stub2allocation3, 0ul); 569 EXPECT_GT(stub3allocation3, 0ul); 570 if (stub1allocation3 != GetMaximumClientAllocation()) 571 EXPECT_LT(stub1allocation3, stub1allocation2); 572 573 stub1.SetVisible(false); 574 575 Manage(); 576 stats = ClientAssignmentCollector::GetClientStatsForLastManage(); 577 uint64 stub1allocation4 = 578 stats[&stub1].allocation.renderer_allocation.bytes_limit_when_visible; 579 uint64 stub2allocation4 = 580 stats[&stub2].allocation.renderer_allocation.bytes_limit_when_visible; 581 uint64 stub3allocation4 = 582 stats[&stub3].allocation.renderer_allocation.bytes_limit_when_visible; 583 584 EXPECT_EQ(stats.size(), 3ul); 585 EXPECT_GT(stub1allocation4, 0ul); 586 EXPECT_GE(stub2allocation4, 0ul); 587 EXPECT_GT(stub3allocation4, 0ul); 588 if (stub3allocation3 != GetMaximumClientAllocation()) 589 EXPECT_GT(stub3allocation4, stub3allocation3); 590 } 591 592 // Test GpuMemoryManager's managed memory tracking 593 TEST_F(GpuMemoryManagerTest, TestManagedUsageTracking) { 594 FakeClient stub1(&memmgr_, GenerateUniqueSurfaceId(), true), 595 stub2(&memmgr_, GenerateUniqueSurfaceId(), false); 596 EXPECT_EQ(0ul, memmgr_.bytes_allocated_managed_visible_); 597 EXPECT_EQ(0ul, memmgr_.bytes_allocated_managed_nonvisible_); 598 599 // Set memory allocations and verify the results are reflected. 600 stub1.SetManagedMemoryStats(GpuManagedMemoryStats(0, 0, 5, false)); 601 stub2.SetManagedMemoryStats(GpuManagedMemoryStats(0, 0, 7, false)); 602 EXPECT_EQ(5ul, memmgr_.bytes_allocated_managed_visible_); 603 EXPECT_EQ(7ul, memmgr_.bytes_allocated_managed_nonvisible_); 604 605 // Remove a visible client 606 stub1.client_state_.reset(); 607 EXPECT_EQ(0ul, memmgr_.bytes_allocated_managed_visible_); 608 EXPECT_EQ(7ul, memmgr_.bytes_allocated_managed_nonvisible_); 609 EXPECT_EQ(0ul, memmgr_.bytes_allocated_managed_visible_); 610 EXPECT_EQ(7ul, memmgr_.bytes_allocated_managed_nonvisible_); 611 stub1.client_state_.reset(memmgr_.CreateClientState(&stub1, true, true)); 612 EXPECT_EQ(0ul, memmgr_.bytes_allocated_managed_visible_); 613 EXPECT_EQ(7ul, memmgr_.bytes_allocated_managed_nonvisible_); 614 stub1.SetManagedMemoryStats(GpuManagedMemoryStats(0, 0, 5, false)); 615 EXPECT_EQ(5ul, memmgr_.bytes_allocated_managed_visible_); 616 EXPECT_EQ(7ul, memmgr_.bytes_allocated_managed_nonvisible_); 617 618 // Remove a nonvisible client 619 stub2.client_state_.reset(); 620 EXPECT_EQ(5ul, memmgr_.bytes_allocated_managed_visible_); 621 EXPECT_EQ(0ul, memmgr_.bytes_allocated_managed_nonvisible_); 622 EXPECT_EQ(5ul, memmgr_.bytes_allocated_managed_visible_); 623 EXPECT_EQ(0ul, memmgr_.bytes_allocated_managed_nonvisible_); 624 stub2.client_state_.reset(memmgr_.CreateClientState(&stub2, true, false)); 625 EXPECT_EQ(5ul, memmgr_.bytes_allocated_managed_visible_); 626 EXPECT_EQ(0ul, memmgr_.bytes_allocated_managed_nonvisible_); 627 stub2.SetManagedMemoryStats(GpuManagedMemoryStats(0, 0, 7, false)); 628 EXPECT_EQ(5ul, memmgr_.bytes_allocated_managed_visible_); 629 EXPECT_EQ(7ul, memmgr_.bytes_allocated_managed_nonvisible_); 630 631 // Create and then destroy some stubs, and verify their allocations go away. 632 { 633 FakeClient stub3(&memmgr_, GenerateUniqueSurfaceId(), true), 634 stub4(&memmgr_, GenerateUniqueSurfaceId(), false); 635 stub3.SetManagedMemoryStats(GpuManagedMemoryStats(0, 0, 1, false)); 636 stub4.SetManagedMemoryStats(GpuManagedMemoryStats(0, 0, 2, false)); 637 EXPECT_EQ(6ul, memmgr_.bytes_allocated_managed_visible_); 638 EXPECT_EQ(9ul, memmgr_.bytes_allocated_managed_nonvisible_); 639 } 640 EXPECT_EQ(5ul, memmgr_.bytes_allocated_managed_visible_); 641 EXPECT_EQ(7ul, memmgr_.bytes_allocated_managed_nonvisible_); 642 643 // Do no-op changes to stubs' visibility and make sure nothing chnages. 644 stub1.SetVisible(true); 645 stub2.SetVisible(false); 646 EXPECT_EQ(5ul, memmgr_.bytes_allocated_managed_visible_); 647 EXPECT_EQ(7ul, memmgr_.bytes_allocated_managed_nonvisible_); 648 649 // Change visbility state. 650 stub1.SetVisible(false); 651 stub2.SetVisible(true); 652 EXPECT_EQ(7ul, memmgr_.bytes_allocated_managed_visible_); 653 EXPECT_EQ(5ul, memmgr_.bytes_allocated_managed_nonvisible_); 654 655 // Increase allocation amounts. 656 stub1.SetManagedMemoryStats(GpuManagedMemoryStats(0, 0, 6, false)); 657 stub2.SetManagedMemoryStats(GpuManagedMemoryStats(0, 0, 8, false)); 658 EXPECT_EQ(8ul, memmgr_.bytes_allocated_managed_visible_); 659 EXPECT_EQ(6ul, memmgr_.bytes_allocated_managed_nonvisible_); 660 661 // Decrease allocation amounts. 662 stub1.SetManagedMemoryStats(GpuManagedMemoryStats(0, 0, 4, false)); 663 stub2.SetManagedMemoryStats(GpuManagedMemoryStats(0, 0, 6, false)); 664 EXPECT_EQ(6ul, memmgr_.bytes_allocated_managed_visible_); 665 EXPECT_EQ(4ul, memmgr_.bytes_allocated_managed_nonvisible_); 666 } 667 668 // Test nonvisible MRU behavior (the most recently used nonvisible clients 669 // keep their contents). 670 TEST_F(GpuMemoryManagerTest, BackgroundMru) { 671 // Set memory manager constants for this test. Note that the budget 672 // for backgrounded content will be 64/4 = 16. 673 memmgr_.TestingSetAvailableGpuMemory(64); 674 memmgr_.TestingSetMinimumClientAllocation(8); 675 676 uint64 bytes_when_not_visible_expected = 6u; 677 if (!memmgr_.allow_nonvisible_memory_) 678 bytes_when_not_visible_expected = 0; 679 680 FakeClient stub1(&memmgr_, GenerateUniqueSurfaceId(), true); 681 FakeClient stub2(&memmgr_, GenerateUniqueSurfaceId(), true); 682 FakeClient stub3(&memmgr_, GenerateUniqueSurfaceId(), true); 683 684 // When all are visible, they should all be allowed to have memory 685 // should they become nonvisible. 686 SetClientStats(&stub1, 6, 23); 687 SetClientStats(&stub2, 6, 23); 688 SetClientStats(&stub3, 6, 23); 689 Manage(); 690 EXPECT_GE(stub1.BytesWhenVisible(), 20u); 691 EXPECT_GE(stub2.BytesWhenVisible(), 20u); 692 EXPECT_GE(stub3.BytesWhenVisible(), 20u); 693 EXPECT_LT(stub1.BytesWhenVisible(), 22u); 694 EXPECT_LT(stub2.BytesWhenVisible(), 22u); 695 EXPECT_LT(stub3.BytesWhenVisible(), 22u); 696 EXPECT_GE(stub1.BytesWhenNotVisible(), bytes_when_not_visible_expected); 697 EXPECT_GE(stub2.BytesWhenNotVisible(), bytes_when_not_visible_expected); 698 EXPECT_GE(stub3.BytesWhenNotVisible(), bytes_when_not_visible_expected); 699 700 // Background stubs 1 and 2, and they should fit. All stubs should 701 // have their full nicetohave budget should they become visible. 702 stub2.SetVisible(false); 703 stub1.SetVisible(false); 704 Manage(); 705 EXPECT_GE(stub1.BytesWhenVisible(), 23u); 706 EXPECT_GE(stub2.BytesWhenVisible(), 23u); 707 EXPECT_GE(stub3.BytesWhenVisible(), 23u); 708 EXPECT_LT(stub1.BytesWhenVisible(), 32u); 709 EXPECT_LT(stub2.BytesWhenVisible(), 32u); 710 EXPECT_GE(stub1.BytesWhenNotVisible(), bytes_when_not_visible_expected); 711 EXPECT_GE(stub2.BytesWhenNotVisible(), bytes_when_not_visible_expected); 712 EXPECT_GE(stub3.BytesWhenNotVisible(), bytes_when_not_visible_expected); 713 714 // Now background stub 3, and it should cause stub 2 to be 715 // evicted because it was set non-visible first 716 stub3.SetVisible(false); 717 Manage(); 718 EXPECT_GE(stub1.BytesWhenNotVisible(), bytes_when_not_visible_expected); 719 EXPECT_EQ(stub2.BytesWhenNotVisible(), 0u); 720 EXPECT_GE(stub3.BytesWhenNotVisible(), bytes_when_not_visible_expected); 721 } 722 723 // Test that once a backgrounded client has dropped its resources, it 724 // doesn't get them back until it becomes visible again. 725 TEST_F(GpuMemoryManagerTest, BackgroundDiscardPersistent) { 726 // Set memory manager constants for this test. Note that the budget 727 // for backgrounded content will be 64/4 = 16. 728 memmgr_.TestingSetAvailableGpuMemory(64); 729 memmgr_.TestingSetMinimumClientAllocation(8); 730 731 uint64 bytes_when_not_visible_expected = 10ul; 732 if (!memmgr_.allow_nonvisible_memory_) 733 bytes_when_not_visible_expected = 0; 734 735 FakeClient stub1(&memmgr_, GenerateUniqueSurfaceId(), true); 736 FakeClient stub2(&memmgr_, GenerateUniqueSurfaceId(), true); 737 738 // Both clients should be able to keep their contents should one of 739 // them become nonvisible. 740 SetClientStats(&stub1, 10, 20); 741 SetClientStats(&stub2, 10, 20); 742 Manage(); 743 EXPECT_GE(stub1.BytesWhenNotVisible(), bytes_when_not_visible_expected); 744 EXPECT_GE(stub2.BytesWhenNotVisible(), bytes_when_not_visible_expected); 745 746 // If they both go nonvisible, then only the most recently used client 747 // should keep its contents. 748 stub1.SetVisible(false); 749 stub2.SetVisible(false); 750 Manage(); 751 EXPECT_EQ(stub1.BytesWhenNotVisible(), 0u); 752 EXPECT_GE(stub2.BytesWhenNotVisible(), bytes_when_not_visible_expected); 753 754 // When becoming visible, stub 2 should get its contents back, and 755 // retain them next time it is made nonvisible. 756 stub2.SetVisible(true); 757 Manage(); 758 EXPECT_GE(stub2.BytesWhenNotVisible(), bytes_when_not_visible_expected); 759 stub2.SetVisible(false); 760 Manage(); 761 EXPECT_GE(stub2.BytesWhenNotVisible(), bytes_when_not_visible_expected); 762 } 763 764 // Test tracking of unmanaged (e.g, WebGL) memory. 765 TEST_F(GpuMemoryManagerTest, UnmanagedTracking) { 766 // Set memory manager constants for this test 767 memmgr_.TestingSetAvailableGpuMemory(64); 768 memmgr_.TestingSetMinimumClientAllocation(8); 769 memmgr_.TestingSetUnmanagedLimitStep(16); 770 771 FakeClient stub1(&memmgr_, GenerateUniqueSurfaceId(), true); 772 773 // Expect that the one stub get its nicetohave level. 774 SetClientStats(&stub1, 16, 32); 775 Manage(); 776 EXPECT_GE(stub1.BytesWhenVisible(), 32u); 777 778 // Now allocate some unmanaged memory and make sure the amount 779 // goes down. 780 memmgr_.TrackMemoryAllocatedChange( 781 stub1.tracking_group_.get(), 782 0, 783 48, 784 gpu::gles2::MemoryTracker::kUnmanaged); 785 Manage(); 786 EXPECT_LT(stub1.BytesWhenVisible(), 24u); 787 788 // Now allocate the entire FB worth of unmanaged memory, and 789 // make sure that we stay stuck at the minimum tab allocation. 790 memmgr_.TrackMemoryAllocatedChange( 791 stub1.tracking_group_.get(), 792 48, 793 64, 794 gpu::gles2::MemoryTracker::kUnmanaged); 795 Manage(); 796 EXPECT_EQ(stub1.BytesWhenVisible(), 8u); 797 798 // Far-oversubscribe the entire FB, and make sure we stay at 799 // the minimum allocation, and don't blow up. 800 memmgr_.TrackMemoryAllocatedChange( 801 stub1.tracking_group_.get(), 802 64, 803 999, 804 gpu::gles2::MemoryTracker::kUnmanaged); 805 Manage(); 806 EXPECT_EQ(stub1.BytesWhenVisible(), 8u); 807 808 // Delete all tracked memory so we don't hit leak checks. 809 memmgr_.TrackMemoryAllocatedChange( 810 stub1.tracking_group_.get(), 811 999, 812 0, 813 gpu::gles2::MemoryTracker::kUnmanaged); 814 } 815 816 // Test the default allocation levels are used. 817 TEST_F(GpuMemoryManagerTest, DefaultAllocation) { 818 // Set memory manager constants for this test 819 memmgr_.TestingSetAvailableGpuMemory(64); 820 memmgr_.TestingSetMinimumClientAllocation(8); 821 memmgr_.TestingSetDefaultClientAllocation(16); 822 823 FakeClient stub1(&memmgr_, GenerateUniqueSurfaceId(), true); 824 825 // Expect that a client which has not sent stats receive at 826 // least the default allocation. 827 Manage(); 828 EXPECT_GE(stub1.BytesWhenVisible(), 829 memmgr_.GetDefaultClientAllocation()); 830 EXPECT_EQ(stub1.BytesWhenNotVisible(), 0u); 831 } 832 833 } // namespace content 834