// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "content/common/gpu/gpu_command_buffer_stub.h" #include "content/common/gpu/gpu_memory_allocation.h" #include "content/common/gpu/gpu_memory_manager.h" #include "ui/gfx/size_conversions.h" #include "testing/gtest/include/gtest/gtest.h" namespace content { class FakeCommandBufferStub : public GpuCommandBufferStubBase { public: MemoryManagerState memory_manager_state_; GpuMemoryAllocation allocation_; gfx::Size size_; FakeCommandBufferStub() : memory_manager_state_(0, false, base::TimeTicks()) { memory_manager_state_.client_has_memory_allocation_changed_callback = true; } FakeCommandBufferStub(int32 surface_id, bool visible, base::TimeTicks last_used_time) : memory_manager_state_(surface_id != 0, visible, last_used_time) { memory_manager_state_.client_has_memory_allocation_changed_callback = true; } virtual const MemoryManagerState& memory_manager_state() const { return memory_manager_state_; } virtual gfx::Size GetSurfaceSize() const { return size_; } virtual bool IsInSameContextShareGroup( const GpuCommandBufferStubBase& stub) const { return false; } virtual void SetMemoryAllocation(const GpuMemoryAllocation& alloc) { allocation_ = alloc; } virtual bool GetTotalGpuMemory(size_t* bytes) { return false; } }; class FakeCommandBufferStubWithoutSurface : public GpuCommandBufferStubBase { public: MemoryManagerState memory_manager_state_; GpuMemoryAllocation allocation_; std::vector share_group_; FakeCommandBufferStubWithoutSurface() : memory_manager_state_(false, true, base::TimeTicks()) { memory_manager_state_.client_has_memory_allocation_changed_callback = true; } virtual const MemoryManagerState& memory_manager_state() const { return memory_manager_state_; } virtual gfx::Size GetSurfaceSize() const { return gfx::Size(); } virtual bool IsInSameContextShareGroup( const GpuCommandBufferStubBase& stub) const { return std::find(share_group_.begin(), share_group_.end(), &stub) != share_group_.end(); } virtual void SetMemoryAllocation(const GpuMemoryAllocation& alloc) { allocation_ = alloc; } virtual bool GetTotalGpuMemory(size_t* bytes) { return false; } }; class FakeClient : public GpuMemoryManagerClient { public: std::vector stubs_; virtual void AppendAllCommandBufferStubs( std::vector& stubs) { stubs.insert(stubs.end(), stubs_.begin(), stubs_.end()); } }; class GpuMemoryManagerTest : public testing::Test { protected: static const size_t kFrontbufferLimitForTest = 3; GpuMemoryManagerTest() : memory_manager_(&client_, kFrontbufferLimitForTest) { } virtual void SetUp() { older_ = base::TimeTicks::FromInternalValue(1); newer_ = base::TimeTicks::FromInternalValue(2); newest_ = base::TimeTicks::FromInternalValue(3); } static int32 GenerateUniqueSurfaceId() { static int32 surface_id_ = 1; return surface_id_++; } static bool IsMoreImportant(GpuCommandBufferStubBase* lhs, GpuCommandBufferStubBase* rhs) { return GpuMemoryManager::StubWithSurfaceComparator()(lhs, rhs); } bool IsAllocationForegroundForSurfaceYes( const GpuMemoryAllocation& alloc) { return alloc.browser_allocation.suggest_have_frontbuffer && alloc.renderer_allocation.have_backbuffer_when_not_visible && alloc.renderer_allocation.bytes_limit_when_visible >= GetMinimumTabAllocation(); } bool IsAllocationBackgroundForSurfaceYes( const GpuMemoryAllocation& alloc) { return alloc.browser_allocation.suggest_have_frontbuffer && !alloc.renderer_allocation.have_backbuffer_when_not_visible && alloc.renderer_allocation.bytes_limit_when_visible == 0; } bool IsAllocationHibernatedForSurfaceYes( const GpuMemoryAllocation& alloc) { return !alloc.browser_allocation.suggest_have_frontbuffer && !alloc.renderer_allocation.have_backbuffer_when_not_visible && alloc.renderer_allocation.bytes_limit_when_visible == 0; } bool IsAllocationForegroundForSurfaceNo( const GpuMemoryAllocation& alloc) { return !alloc.browser_allocation.suggest_have_frontbuffer && !alloc.renderer_allocation.have_backbuffer_when_not_visible && alloc.renderer_allocation.bytes_limit_when_visible == GetMinimumTabAllocation(); } bool IsAllocationBackgroundForSurfaceNo( const GpuMemoryAllocation& alloc) { return !alloc.browser_allocation.suggest_have_frontbuffer && !alloc.renderer_allocation.have_backbuffer_when_not_visible && alloc.renderer_allocation.bytes_limit_when_visible == GetMinimumTabAllocation(); } bool IsAllocationHibernatedForSurfaceNo( const GpuMemoryAllocation& alloc) { return !alloc.browser_allocation.suggest_have_frontbuffer && !alloc.renderer_allocation.have_backbuffer_when_not_visible && alloc.renderer_allocation.bytes_limit_when_visible == 0; } void Manage() { memory_manager_.Manage(); } size_t GetAvailableGpuMemory() { return memory_manager_.GetAvailableGpuMemory(); } size_t GetMaximumTabAllocation() { return memory_manager_.GetMaximumTabAllocation(); } size_t GetMinimumTabAllocation() { return memory_manager_.GetMinimumTabAllocation(); } base::TimeTicks older_, newer_, newest_; FakeClient client_; GpuMemoryManager memory_manager_; }; // Create fake stubs with every combination of {visibilty,last_use_time} // and make sure they compare correctly. Only compare stubs with surfaces. // Expect {more visible, newer} surfaces to be more important, in that order. TEST_F(GpuMemoryManagerTest, ComparatorTests) { FakeCommandBufferStub stub_true1(GenerateUniqueSurfaceId(), true, older_), stub_true2(GenerateUniqueSurfaceId(), true, newer_), stub_true3(GenerateUniqueSurfaceId(), true, newest_), stub_false1(GenerateUniqueSurfaceId(), false, older_), stub_false2(GenerateUniqueSurfaceId(), false, newer_), stub_false3(GenerateUniqueSurfaceId(), false, newest_); // Should never be more important than self: EXPECT_FALSE(IsMoreImportant(&stub_true1, &stub_true1)); EXPECT_FALSE(IsMoreImportant(&stub_true2, &stub_true2)); EXPECT_FALSE(IsMoreImportant(&stub_true3, &stub_true3)); EXPECT_FALSE(IsMoreImportant(&stub_false1, &stub_false1)); EXPECT_FALSE(IsMoreImportant(&stub_false2, &stub_false2)); EXPECT_FALSE(IsMoreImportant(&stub_false3, &stub_false3)); // Visible should always be more important than non visible: EXPECT_TRUE(IsMoreImportant(&stub_true1, &stub_false1)); EXPECT_TRUE(IsMoreImportant(&stub_true1, &stub_false2)); EXPECT_TRUE(IsMoreImportant(&stub_true1, &stub_false3)); EXPECT_TRUE(IsMoreImportant(&stub_true2, &stub_false1)); EXPECT_TRUE(IsMoreImportant(&stub_true2, &stub_false2)); EXPECT_TRUE(IsMoreImportant(&stub_true2, &stub_false3)); EXPECT_TRUE(IsMoreImportant(&stub_true3, &stub_false1)); EXPECT_TRUE(IsMoreImportant(&stub_true3, &stub_false2)); EXPECT_TRUE(IsMoreImportant(&stub_true3, &stub_false3)); // Not visible should never be more important than visible: EXPECT_FALSE(IsMoreImportant(&stub_false1, &stub_true1)); EXPECT_FALSE(IsMoreImportant(&stub_false1, &stub_true2)); EXPECT_FALSE(IsMoreImportant(&stub_false1, &stub_true3)); EXPECT_FALSE(IsMoreImportant(&stub_false2, &stub_true1)); EXPECT_FALSE(IsMoreImportant(&stub_false2, &stub_true2)); EXPECT_FALSE(IsMoreImportant(&stub_false2, &stub_true3)); EXPECT_FALSE(IsMoreImportant(&stub_false3, &stub_true1)); EXPECT_FALSE(IsMoreImportant(&stub_false3, &stub_true2)); EXPECT_FALSE(IsMoreImportant(&stub_false3, &stub_true3)); // Newer should always be more important than older: EXPECT_TRUE(IsMoreImportant(&stub_true2, &stub_true1)); EXPECT_TRUE(IsMoreImportant(&stub_true3, &stub_true1)); EXPECT_TRUE(IsMoreImportant(&stub_true3, &stub_true2)); EXPECT_TRUE(IsMoreImportant(&stub_false2, &stub_false1)); EXPECT_TRUE(IsMoreImportant(&stub_false3, &stub_false1)); EXPECT_TRUE(IsMoreImportant(&stub_false3, &stub_false2)); // Older should never be more important than newer: EXPECT_FALSE(IsMoreImportant(&stub_true1, &stub_true2)); EXPECT_FALSE(IsMoreImportant(&stub_true1, &stub_true3)); EXPECT_FALSE(IsMoreImportant(&stub_true2, &stub_true3)); EXPECT_FALSE(IsMoreImportant(&stub_false1, &stub_false2)); EXPECT_FALSE(IsMoreImportant(&stub_false1, &stub_false3)); EXPECT_FALSE(IsMoreImportant(&stub_false2, &stub_false3)); } // Test GpuMemoryManager::Manage basic functionality. // Expect memory allocation to set suggest_have_frontbuffer/backbuffer // according to visibility and last used time for stubs with surface. // Expect memory allocation to be shared according to share groups for stubs // without a surface. TEST_F(GpuMemoryManagerTest, TestManageBasicFunctionality) { // Test stubs with surface. FakeCommandBufferStub stub1(GenerateUniqueSurfaceId(), true, older_), stub2(GenerateUniqueSurfaceId(), false, older_); client_.stubs_.push_back(&stub1); client_.stubs_.push_back(&stub2); Manage(); EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub1.allocation_)); EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2.allocation_)); // Test stubs without surface, with share group of 1 stub. FakeCommandBufferStubWithoutSurface stub3, stub4; stub3.share_group_.push_back(&stub1); stub4.share_group_.push_back(&stub2); client_.stubs_.push_back(&stub3); client_.stubs_.push_back(&stub4); Manage(); EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub1.allocation_)); EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2.allocation_)); EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub3.allocation_)); EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub4.allocation_)); // Test stub without surface, with share group of multiple stubs. FakeCommandBufferStubWithoutSurface stub5; stub5.share_group_.push_back(&stub1); stub5.share_group_.push_back(&stub2); client_.stubs_.push_back(&stub5); Manage(); EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub4.allocation_)); } // Test GpuMemoryManager::Manage functionality: changing visibility. // Expect memory allocation to set suggest_have_frontbuffer/backbuffer // according to visibility and last used time for stubs with surface. // Expect memory allocation to be shared according to share groups for stubs // without a surface. TEST_F(GpuMemoryManagerTest, TestManageChangingVisibility) { FakeCommandBufferStub stub1(GenerateUniqueSurfaceId(), true, older_), stub2(GenerateUniqueSurfaceId(), false, older_); client_.stubs_.push_back(&stub1); client_.stubs_.push_back(&stub2); FakeCommandBufferStubWithoutSurface stub3, stub4; stub3.share_group_.push_back(&stub1); stub4.share_group_.push_back(&stub2); client_.stubs_.push_back(&stub3); client_.stubs_.push_back(&stub4); FakeCommandBufferStubWithoutSurface stub5; stub5.share_group_.push_back(&stub1); stub5.share_group_.push_back(&stub2); client_.stubs_.push_back(&stub5); Manage(); EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub1.allocation_)); EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2.allocation_)); EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub3.allocation_)); EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub4.allocation_)); EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub5.allocation_)); stub1.memory_manager_state_.visible = false; stub2.memory_manager_state_.visible = true; Manage(); EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub1.allocation_)); EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub2.allocation_)); EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub3.allocation_)); EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub4.allocation_)); EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub5.allocation_)); } // Test GpuMemoryManager::Manage functionality: Test more than threshold number // of visible stubs. // Expect all allocations to continue to have frontbuffer. TEST_F(GpuMemoryManagerTest, TestManageManyVisibleStubs) { FakeCommandBufferStub stub1(GenerateUniqueSurfaceId(), true, older_), stub2(GenerateUniqueSurfaceId(), true, older_), stub3(GenerateUniqueSurfaceId(), true, older_), stub4(GenerateUniqueSurfaceId(), true, older_); client_.stubs_.push_back(&stub1); client_.stubs_.push_back(&stub2); client_.stubs_.push_back(&stub3); client_.stubs_.push_back(&stub4); FakeCommandBufferStubWithoutSurface stub5, stub6; stub5.share_group_.push_back(&stub1); stub6.share_group_.push_back(&stub2); client_.stubs_.push_back(&stub5); client_.stubs_.push_back(&stub6); FakeCommandBufferStubWithoutSurface stub7; stub7.share_group_.push_back(&stub1); stub7.share_group_.push_back(&stub2); client_.stubs_.push_back(&stub7); Manage(); EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub1.allocation_)); EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub2.allocation_)); EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub3.allocation_)); EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub4.allocation_)); EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub5.allocation_)); EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub6.allocation_)); EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub7.allocation_)); } // Test GpuMemoryManager::Manage functionality: Test more than threshold number // of not visible stubs. // Expect the stubs surpassing the threshold to not have a backbuffer. TEST_F(GpuMemoryManagerTest, TestManageManyNotVisibleStubs) { FakeCommandBufferStub stub1(GenerateUniqueSurfaceId(), false, newer_), stub2(GenerateUniqueSurfaceId(), false, newer_), stub3(GenerateUniqueSurfaceId(), false, newer_), stub4(GenerateUniqueSurfaceId(), false, older_); client_.stubs_.push_back(&stub1); client_.stubs_.push_back(&stub2); client_.stubs_.push_back(&stub3); client_.stubs_.push_back(&stub4); FakeCommandBufferStubWithoutSurface stub5, stub6; stub5.share_group_.push_back(&stub1); stub6.share_group_.push_back(&stub4); client_.stubs_.push_back(&stub5); client_.stubs_.push_back(&stub6); FakeCommandBufferStubWithoutSurface stub7; stub7.share_group_.push_back(&stub1); stub7.share_group_.push_back(&stub4); client_.stubs_.push_back(&stub7); Manage(); EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub1.allocation_)); EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2.allocation_)); EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub3.allocation_)); EXPECT_TRUE(IsAllocationHibernatedForSurfaceYes(stub4.allocation_)); EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub5.allocation_)); EXPECT_TRUE(IsAllocationHibernatedForSurfaceNo(stub6.allocation_)); EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub7.allocation_)); } // Test GpuMemoryManager::Manage functionality: Test changing the last used // time of stubs when doing so causes change in which stubs surpass threshold. // Expect frontbuffer to be dropped for the older stub. TEST_F(GpuMemoryManagerTest, TestManageChangingLastUsedTime) { FakeCommandBufferStub stub1(GenerateUniqueSurfaceId(), false, newer_), stub2(GenerateUniqueSurfaceId(), false, newer_), stub3(GenerateUniqueSurfaceId(), false, newer_), stub4(GenerateUniqueSurfaceId(), false, older_); client_.stubs_.push_back(&stub1); client_.stubs_.push_back(&stub2); client_.stubs_.push_back(&stub3); client_.stubs_.push_back(&stub4); FakeCommandBufferStubWithoutSurface stub5, stub6; stub5.share_group_.push_back(&stub3); stub6.share_group_.push_back(&stub4); client_.stubs_.push_back(&stub5); client_.stubs_.push_back(&stub6); FakeCommandBufferStubWithoutSurface stub7; stub7.share_group_.push_back(&stub3); stub7.share_group_.push_back(&stub4); client_.stubs_.push_back(&stub7); Manage(); EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub1.allocation_)); EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2.allocation_)); EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub3.allocation_)); EXPECT_TRUE(IsAllocationHibernatedForSurfaceYes(stub4.allocation_)); EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub5.allocation_)); EXPECT_TRUE(IsAllocationHibernatedForSurfaceNo(stub6.allocation_)); EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub7.allocation_)); stub3.memory_manager_state_.last_used_time = older_; stub4.memory_manager_state_.last_used_time = newer_; Manage(); EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub1.allocation_)); EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2.allocation_)); EXPECT_TRUE(IsAllocationHibernatedForSurfaceYes(stub3.allocation_)); EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub4.allocation_)); EXPECT_TRUE(IsAllocationHibernatedForSurfaceNo(stub5.allocation_)); EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub6.allocation_)); EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub7.allocation_)); } // Test GpuMemoryManager::Manage functionality: Test changing importance of // enough stubs so that every stub in share group crosses threshold. // Expect memory allocation of the stubs without surface to share memory // allocation with the most visible stub in share group. TEST_F(GpuMemoryManagerTest, TestManageChangingImportanceShareGroup) { FakeCommandBufferStub stubIgnoreA(GenerateUniqueSurfaceId(), true, newer_), stubIgnoreB(GenerateUniqueSurfaceId(), false, newer_), stubIgnoreC(GenerateUniqueSurfaceId(), false, newer_); FakeCommandBufferStub stub1(GenerateUniqueSurfaceId(), true, newest_), stub2(GenerateUniqueSurfaceId(), true, newest_); client_.stubs_.push_back(&stubIgnoreA); client_.stubs_.push_back(&stubIgnoreB); client_.stubs_.push_back(&stubIgnoreC); client_.stubs_.push_back(&stub1); client_.stubs_.push_back(&stub2); FakeCommandBufferStubWithoutSurface stub3, stub4; stub3.share_group_.push_back(&stub1); stub3.share_group_.push_back(&stub2); stub4.share_group_.push_back(&stub1); stub4.share_group_.push_back(&stub2); client_.stubs_.push_back(&stub3); client_.stubs_.push_back(&stub4); Manage(); EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub1.allocation_)); EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub2.allocation_)); EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub3.allocation_)); EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub4.allocation_)); stub1.memory_manager_state_.visible = false; Manage(); EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub1.allocation_)); EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub2.allocation_)); EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub3.allocation_)); EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub4.allocation_)); stub2.memory_manager_state_.visible = false; Manage(); EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub1.allocation_)); EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2.allocation_)); EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub3.allocation_)); EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub4.allocation_)); stub1.memory_manager_state_.last_used_time = older_; Manage(); EXPECT_TRUE(IsAllocationHibernatedForSurfaceYes(stub1.allocation_)); EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2.allocation_)); EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub3.allocation_)); EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub4.allocation_)); stub2.memory_manager_state_.last_used_time = older_; Manage(); EXPECT_TRUE(IsAllocationHibernatedForSurfaceYes(stub1.allocation_)); EXPECT_TRUE(IsAllocationHibernatedForSurfaceYes(stub2.allocation_)); EXPECT_TRUE(IsAllocationHibernatedForSurfaceNo(stub3.allocation_)); EXPECT_TRUE(IsAllocationHibernatedForSurfaceNo(stub4.allocation_)); } #if !defined(OS_ANDROID) // Test GpuMemoryAllocation memory allocation bonuses: // When the number of visible tabs is small, each tab should get a // gpu_resource_size_in_bytes allocation value that is greater than // GetMinimumTabAllocation(), and when the number of tabs is large, each should // get exactly GetMinimumTabAllocation() and not less. TEST_F(GpuMemoryManagerTest, TestForegroundStubsGetBonusAllocation) { size_t max_stubs_before_no_bonus = GetAvailableGpuMemory() / (GetMinimumTabAllocation() + 1); std::vector stubs; for (size_t i = 0; i < max_stubs_before_no_bonus; ++i) { stubs.push_back( FakeCommandBufferStub(GenerateUniqueSurfaceId(), true, older_)); } for (size_t i = 0; i < stubs.size(); ++i) { client_.stubs_.push_back(&stubs[i]); } Manage(); for (size_t i = 0; i < stubs.size(); ++i) { EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stubs[i].allocation_)); EXPECT_GT( stubs[i].allocation_.renderer_allocation.bytes_limit_when_visible, static_cast(GetMinimumTabAllocation())); } FakeCommandBufferStub extra_stub(GenerateUniqueSurfaceId(), true, older_); client_.stubs_.push_back(&extra_stub); Manage(); for (size_t i = 0; i < stubs.size(); ++i) { EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stubs[i].allocation_)); EXPECT_EQ( stubs[i].allocation_.renderer_allocation.bytes_limit_when_visible, GetMinimumTabAllocation()); } } #else // Test GpuMemoryAllocation memory allocation bonuses: // When the size of tab contents is small, bonus allocation should be 0. // As the size of tab contents increases, bonus allocation should increase // until finally reaching the maximum allocation limit. TEST_F(GpuMemoryManagerTest, TestForegroundStubsGetBonusAllocationAndroid) { FakeCommandBufferStub stub(GenerateUniqueSurfaceId(), true, older_); client_.stubs_.push_back(&stub); stub.size_ = gfx::Size(1,1); Manage(); EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub.allocation_)); EXPECT_EQ(stub.allocation_.renderer_allocation.bytes_limit_when_visible, GetMinimumTabAllocation()); // Keep increasing size, making sure allocation is always increasing // Until it finally reaches the maximum. while (stub.allocation_.renderer_allocation.bytes_limit_when_visible < GetAvailableGpuMemory()) { size_t previous_allocation = stub.allocation_.renderer_allocation.bytes_limit_when_visible; stub.size_ = gfx::ToFlooredSize(stub.size_.Scale(1, 2)); Manage(); EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub.allocation_)); EXPECT_GE(stub.allocation_.renderer_allocation.bytes_limit_when_visible, GetMinimumTabAllocation()); EXPECT_LE(stub.allocation_.renderer_allocation.bytes_limit_when_visible, GetAvailableGpuMemory()); EXPECT_GE(stub.allocation_.renderer_allocation.bytes_limit_when_visible, previous_allocation); } // One final size increase to confirm it stays capped at maximum. stub.size_ = gfx::ToFlooredSize(stub.size_.Scale(1, 2)); Manage(); EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub.allocation_)); EXPECT_EQ(stub.allocation_.renderer_allocation.bytes_limit_when_visible, GetAvailableGpuMemory()); } #endif // Test GpuMemoryAllocation comparison operators: Iterate over all possible // combinations of gpu_resource_size_in_bytes, suggest_have_backbuffer, and // suggest_have_frontbuffer, and make sure allocations with equal values test // equal and non equal values test not equal. TEST_F(GpuMemoryManagerTest, GpuMemoryAllocationCompareTests) { std::vector gpu_resource_size_in_bytes_values; gpu_resource_size_in_bytes_values.push_back(0); gpu_resource_size_in_bytes_values.push_back(1); gpu_resource_size_in_bytes_values.push_back(12345678); std::vector suggested_buffer_allocation_values; suggested_buffer_allocation_values.push_back( GpuMemoryAllocation::kHasFrontbuffer | GpuMemoryAllocation::kHasBackbuffer); suggested_buffer_allocation_values.push_back( GpuMemoryAllocation::kHasFrontbuffer); suggested_buffer_allocation_values.push_back( GpuMemoryAllocation::kHasBackbuffer); suggested_buffer_allocation_values.push_back( GpuMemoryAllocation::kHasNoBuffers); for(size_t i = 0; i != gpu_resource_size_in_bytes_values.size(); ++i) { for(size_t j = 0; j != suggested_buffer_allocation_values.size(); ++j) { int sz = gpu_resource_size_in_bytes_values[i]; int buffer_allocation = suggested_buffer_allocation_values[j]; GpuMemoryAllocation allocation(sz, buffer_allocation); EXPECT_TRUE(allocation.Equals( GpuMemoryAllocation(sz, buffer_allocation))); EXPECT_FALSE(allocation.Equals( GpuMemoryAllocation(sz+1, buffer_allocation))); for(size_t k = 0; k != suggested_buffer_allocation_values.size(); ++k) { int buffer_allocation_other = suggested_buffer_allocation_values[k]; if (buffer_allocation == buffer_allocation_other) continue; EXPECT_FALSE(allocation.Equals( GpuMemoryAllocation(sz, buffer_allocation_other))); } } } } // Test GpuMemoryManager Stub Memory Stats functionality: // Creats various surface/non-surface stubs and switches stub visibility and // tests to see that stats data structure values are correct. TEST_F(GpuMemoryManagerTest, StubMemoryStatsForLastManageTests) { #if !defined(OS_ANDROID) const bool compositors_get_bonus_allocation = true; #else const bool compositors_get_bonus_allocation = false; #endif GpuMemoryManager::StubMemoryStatMap stats; Manage(); stats = memory_manager_.stub_memory_stats_for_last_manage(); EXPECT_EQ(stats.size(), 0ul); FakeCommandBufferStub stub1(GenerateUniqueSurfaceId(), true, older_); client_.stubs_.push_back(&stub1); Manage(); stats = memory_manager_.stub_memory_stats_for_last_manage(); size_t stub1allocation1 = stats[&stub1].allocation.renderer_allocation.bytes_limit_when_visible; EXPECT_EQ(stats.size(), 1ul); EXPECT_TRUE(stats[&stub1].visible); EXPECT_GT(stub1allocation1, 0ul); FakeCommandBufferStubWithoutSurface stub2; client_.stubs_.push_back(&stub2); stub2.share_group_.push_back(&stub1); Manage(); stats = memory_manager_.stub_memory_stats_for_last_manage(); size_t stub1allocation2 = stats[&stub1].allocation.renderer_allocation.bytes_limit_when_visible; size_t stub2allocation2 = stats[&stub2].allocation.renderer_allocation.bytes_limit_when_visible; EXPECT_EQ(stats.size(), 2ul); EXPECT_TRUE(stats[&stub1].visible); EXPECT_TRUE(stats[&stub2].visible); EXPECT_GT(stub1allocation2, 0ul); EXPECT_GT(stub2allocation2, 0ul); if (compositors_get_bonus_allocation && stub1allocation2 != GetMaximumTabAllocation()) EXPECT_LT(stub1allocation2, stub1allocation1); FakeCommandBufferStub stub3(GenerateUniqueSurfaceId(), true, older_); client_.stubs_.push_back(&stub3); Manage(); stats = memory_manager_.stub_memory_stats_for_last_manage(); size_t stub1allocation3 = stats[&stub1].allocation.renderer_allocation.bytes_limit_when_visible; size_t stub2allocation3 = stats[&stub2].allocation.renderer_allocation.bytes_limit_when_visible; size_t stub3allocation3 = stats[&stub3].allocation.renderer_allocation.bytes_limit_when_visible; EXPECT_EQ(stats.size(), 3ul); EXPECT_TRUE(stats[&stub1].visible); EXPECT_TRUE(stats[&stub2].visible); EXPECT_TRUE(stats[&stub3].visible); EXPECT_GT(stub1allocation3, 0ul); EXPECT_GT(stub2allocation3, 0ul); EXPECT_GT(stub3allocation3, 0ul); if (compositors_get_bonus_allocation && stub1allocation3 != GetMaximumTabAllocation()) EXPECT_LT(stub1allocation3, stub1allocation2); stub1.memory_manager_state_.visible = false; Manage(); stats = memory_manager_.stub_memory_stats_for_last_manage(); size_t stub1allocation4 = stats[&stub1].allocation.renderer_allocation.bytes_limit_when_visible; size_t stub2allocation4 = stats[&stub2].allocation.renderer_allocation.bytes_limit_when_visible; size_t stub3allocation4 = stats[&stub3].allocation.renderer_allocation.bytes_limit_when_visible; EXPECT_EQ(stats.size(), 3ul); EXPECT_FALSE(stats[&stub1].visible); EXPECT_FALSE(stats[&stub2].visible); EXPECT_TRUE(stats[&stub3].visible); EXPECT_EQ(stub1allocation4, 0ul); EXPECT_GE(stub2allocation4, 0ul); EXPECT_GT(stub3allocation4, 0ul); if (compositors_get_bonus_allocation && stub3allocation3 != GetMaximumTabAllocation()) EXPECT_GT(stub3allocation4, stub3allocation3); } } // namespace content