This source file includes following definitions.
- TrackMemoryAllocatedChange
- EnsureGPUMemoryAvailable
- GetClientStatsForLastManage
- ClearAllStats
- AddClientStat
- memory_tracker_
- memory_tracker_
- SetMemoryAllocation
- SuggestHaveFrontBuffer
- GetTotalGpuMemory
- SetTotalGpuMemory
- GetMemoryTracker
- GetSurfaceSize
- SetSurfaceSize
- SetVisible
- SetManagedMemoryStats
- BytesWhenVisible
- SetUp
- GenerateUniqueSurfaceId
- IsAllocationForegroundForSurfaceYes
- IsAllocationBackgroundForSurfaceYes
- IsAllocationHibernatedForSurfaceYes
- IsAllocationForegroundForSurfaceNo
- IsAllocationBackgroundForSurfaceNo
- IsAllocationHibernatedForSurfaceNo
- Manage
- CalcAvailableFromGpuTotal
- CalcAvailableClamped
- GetAvailableGpuMemory
- GetMaximumClientAllocation
- GetMinimumClientAllocation
- SetClientStats
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
#include "content/common/gpu/gpu_memory_manager.h"
#include "content/common/gpu/gpu_memory_manager_client.h"
#include "content/common/gpu/gpu_memory_tracking.h"
#include "gpu/command_buffer/common/gpu_memory_allocation.h"
#include "ui/gfx/size_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
using gpu::MemoryAllocation;
using gpu::ManagedMemoryStats;
#if defined(COMPILER_GCC)
namespace BASE_HASH_NAMESPACE {
template<>
struct hash<content::GpuMemoryManagerClient*> {
uint64 operator()(content::GpuMemoryManagerClient* ptr) const {
return hash<uint64>()(reinterpret_cast<uint64>(ptr));
}
};
}
#endif
class FakeMemoryTracker : public gpu::gles2::MemoryTracker {
public:
virtual void TrackMemoryAllocatedChange(
size_t ,
size_t ,
gpu::gles2::MemoryTracker::Pool ) OVERRIDE {
}
virtual bool EnsureGPUMemoryAvailable(size_t ) OVERRIDE {
return true;
}
private:
virtual ~FakeMemoryTracker() {
}
};
namespace content {
class ClientAssignmentCollector {
public:
struct ClientMemoryStat {
MemoryAllocation allocation;
};
typedef base::hash_map<GpuMemoryManagerClient*, ClientMemoryStat>
ClientMemoryStatMap;
static const ClientMemoryStatMap& GetClientStatsForLastManage() {
return client_memory_stats_for_last_manage_;
}
static void ClearAllStats() {
client_memory_stats_for_last_manage_.clear();
}
static void AddClientStat(GpuMemoryManagerClient* client,
const MemoryAllocation& allocation) {
DCHECK(!client_memory_stats_for_last_manage_.count(client));
client_memory_stats_for_last_manage_[client].allocation = allocation;
}
private:
static ClientMemoryStatMap client_memory_stats_for_last_manage_;
};
ClientAssignmentCollector::ClientMemoryStatMap
ClientAssignmentCollector::client_memory_stats_for_last_manage_;
class FakeClient : public GpuMemoryManagerClient {
public:
GpuMemoryManager* memmgr_;
bool suggest_have_frontbuffer_;
MemoryAllocation allocation_;
uint64 total_gpu_memory_;
gfx::Size surface_size_;
GpuMemoryManagerClient* share_group_;
scoped_refptr<gpu::gles2::MemoryTracker> memory_tracker_;
scoped_ptr<GpuMemoryTrackingGroup> tracking_group_;
scoped_ptr<GpuMemoryManagerClientState> client_state_;
FakeClient(GpuMemoryManager* memmgr, GpuMemoryManagerClient* share_group)
: memmgr_(memmgr),
suggest_have_frontbuffer_(false),
total_gpu_memory_(0),
share_group_(share_group),
memory_tracker_(NULL) {
if (!share_group_) {
memory_tracker_ = new FakeMemoryTracker();
tracking_group_.reset(
memmgr_->CreateTrackingGroup(0, memory_tracker_.get()));
}
client_state_.reset(memmgr_->CreateClientState(this, false, true));
}
FakeClient(GpuMemoryManager* memmgr, int32 surface_id, bool visible)
: memmgr_(memmgr),
suggest_have_frontbuffer_(false),
total_gpu_memory_(0),
share_group_(NULL),
memory_tracker_(NULL) {
memory_tracker_ = new FakeMemoryTracker();
tracking_group_.reset(
memmgr_->CreateTrackingGroup(0, memory_tracker_.get()));
client_state_.reset(
memmgr_->CreateClientState(this, surface_id != 0, visible));
}
virtual ~FakeClient() {
client_state_.reset();
tracking_group_.reset();
memory_tracker_ = NULL;
}
virtual void SetMemoryAllocation(const MemoryAllocation& alloc) OVERRIDE {
allocation_ = alloc;
ClientAssignmentCollector::AddClientStat(this, alloc);
}
virtual void SuggestHaveFrontBuffer(bool suggest_have_frontbuffer) OVERRIDE {
suggest_have_frontbuffer_ = suggest_have_frontbuffer;
}
virtual bool GetTotalGpuMemory(uint64* bytes) OVERRIDE {
if (total_gpu_memory_) {
*bytes = total_gpu_memory_;
return true;
}
return false;
}
void SetTotalGpuMemory(uint64 bytes) { total_gpu_memory_ = bytes; }
virtual gpu::gles2::MemoryTracker* GetMemoryTracker() const OVERRIDE {
if (share_group_)
return share_group_->GetMemoryTracker();
return memory_tracker_.get();
}
virtual gfx::Size GetSurfaceSize() const OVERRIDE {
return surface_size_;
}
void SetSurfaceSize(gfx::Size size) { surface_size_ = size; }
void SetVisible(bool visible) {
client_state_->SetVisible(visible);
}
void SetManagedMemoryStats(const ManagedMemoryStats& stats) {
client_state_->SetManagedMemoryStats(stats);
}
uint64 BytesWhenVisible() const {
return allocation_.bytes_limit_when_visible;
}
};
class GpuMemoryManagerTest : public testing::Test {
protected:
static const uint64 kFrontbufferLimitForTest = 3;
GpuMemoryManagerTest()
: memmgr_(0, kFrontbufferLimitForTest) {
memmgr_.TestingDisableScheduleManage();
}
virtual void SetUp() {
}
static int32 GenerateUniqueSurfaceId() {
static int32 surface_id_ = 1;
return surface_id_++;
}
bool IsAllocationForegroundForSurfaceYes(
const MemoryAllocation& alloc) {
return true;
}
bool IsAllocationBackgroundForSurfaceYes(
const MemoryAllocation& alloc) {
return true;
}
bool IsAllocationHibernatedForSurfaceYes(
const MemoryAllocation& alloc) {
return true;
}
bool IsAllocationForegroundForSurfaceNo(
const MemoryAllocation& alloc) {
return alloc.bytes_limit_when_visible ==
GetMinimumClientAllocation();
}
bool IsAllocationBackgroundForSurfaceNo(
const MemoryAllocation& alloc) {
return alloc.bytes_limit_when_visible ==
GetMinimumClientAllocation();
}
bool IsAllocationHibernatedForSurfaceNo(
const MemoryAllocation& alloc) {
return alloc.bytes_limit_when_visible == 0;
}
void Manage() {
ClientAssignmentCollector::ClearAllStats();
memmgr_.Manage();
}
uint64 CalcAvailableFromGpuTotal(uint64 bytes) {
return GpuMemoryManager::CalcAvailableFromGpuTotal(bytes);
}
uint64 CalcAvailableClamped(uint64 bytes) {
bytes = std::max(bytes, memmgr_.GetDefaultAvailableGpuMemory());
bytes = std::min(bytes, memmgr_.GetMaximumTotalGpuMemory());
return bytes;
}
uint64 GetAvailableGpuMemory() {
return memmgr_.GetAvailableGpuMemory();
}
uint64 GetMaximumClientAllocation() {
return memmgr_.GetMaximumClientAllocation();
}
uint64 GetMinimumClientAllocation() {
return memmgr_.GetMinimumClientAllocation();
}
void SetClientStats(
FakeClient* client,
uint64 required,
uint64 nicetohave) {
client->SetManagedMemoryStats(
ManagedMemoryStats(required, nicetohave, 0, false));
}
GpuMemoryManager memmgr_;
};
TEST_F(GpuMemoryManagerTest, TestManageBasicFunctionality) {
FakeClient stub1(&memmgr_, GenerateUniqueSurfaceId(), true),
stub2(&memmgr_, GenerateUniqueSurfaceId(), false);
Manage();
EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub1.allocation_));
EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2.allocation_));
FakeClient stub3(&memmgr_, &stub1), stub4(&memmgr_, &stub2);
Manage();
EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub1.allocation_));
EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2.allocation_));
EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub3.allocation_));
EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub4.allocation_));
FakeClient stub5(&memmgr_ , &stub2);
Manage();
EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub4.allocation_));
}
TEST_F(GpuMemoryManagerTest, TestManageChangingVisibility) {
FakeClient stub1(&memmgr_, GenerateUniqueSurfaceId(), true),
stub2(&memmgr_, GenerateUniqueSurfaceId(), false);
FakeClient stub3(&memmgr_, &stub1), stub4(&memmgr_, &stub2);
FakeClient stub5(&memmgr_ , &stub2);
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.SetVisible(false);
stub2.SetVisible(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_F(GpuMemoryManagerTest, TestManageManyVisibleStubs) {
FakeClient stub1(&memmgr_, GenerateUniqueSurfaceId(), true),
stub2(&memmgr_, GenerateUniqueSurfaceId(), true),
stub3(&memmgr_, GenerateUniqueSurfaceId(), true),
stub4(&memmgr_, GenerateUniqueSurfaceId(), true);
FakeClient stub5(&memmgr_ , &stub1), stub6(&memmgr_ , &stub2);
FakeClient stub7(&memmgr_ , &stub2);
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_F(GpuMemoryManagerTest, TestManageManyNotVisibleStubs) {
FakeClient stub1(&memmgr_, GenerateUniqueSurfaceId(), true),
stub2(&memmgr_, GenerateUniqueSurfaceId(), true),
stub3(&memmgr_, GenerateUniqueSurfaceId(), true),
stub4(&memmgr_, GenerateUniqueSurfaceId(), true);
stub4.SetVisible(false);
stub3.SetVisible(false);
stub2.SetVisible(false);
stub1.SetVisible(false);
FakeClient stub5(&memmgr_ , &stub1), stub6(&memmgr_ , &stub4);
FakeClient stub7(&memmgr_ , &stub1);
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_F(GpuMemoryManagerTest, TestManageChangingLastUsedTime) {
FakeClient stub1(&memmgr_, GenerateUniqueSurfaceId(), true),
stub2(&memmgr_, GenerateUniqueSurfaceId(), true),
stub3(&memmgr_, GenerateUniqueSurfaceId(), true),
stub4(&memmgr_, GenerateUniqueSurfaceId(), true);
FakeClient stub5(&memmgr_ , &stub3), stub6(&memmgr_ , &stub4);
FakeClient stub7(&memmgr_ , &stub3);
stub4.SetVisible(false);
stub3.SetVisible(false);
stub2.SetVisible(false);
stub1.SetVisible(false);
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_));
stub2.SetVisible(true);
stub2.SetVisible(false);
stub4.SetVisible(true);
stub4.SetVisible(false);
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(IsAllocationHibernatedForSurfaceNo(stub7.allocation_));
}
TEST_F(GpuMemoryManagerTest, TestManageChangingImportanceShareGroup) {
FakeClient stub_ignore_a(&memmgr_, GenerateUniqueSurfaceId(), true),
stub_ignore_b(&memmgr_, GenerateUniqueSurfaceId(), false),
stub_ignore_c(&memmgr_, GenerateUniqueSurfaceId(), false);
FakeClient stub1(&memmgr_, GenerateUniqueSurfaceId(), false),
stub2(&memmgr_, GenerateUniqueSurfaceId(), false);
FakeClient stub3(&memmgr_, &stub2), stub4(&memmgr_, &stub2);
stub1.SetVisible(true);
stub2.SetVisible(true);
Manage();
EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub1.allocation_));
EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub2.allocation_));
EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub3.allocation_));
EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub4.allocation_));
stub1.SetVisible(false);
Manage();
EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub1.allocation_));
EXPECT_TRUE(IsAllocationForegroundForSurfaceYes(stub2.allocation_));
EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub3.allocation_));
EXPECT_TRUE(IsAllocationForegroundForSurfaceNo(stub4.allocation_));
stub2.SetVisible(false);
Manage();
EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub1.allocation_));
EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2.allocation_));
EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub3.allocation_));
EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub4.allocation_));
stub_ignore_b.SetVisible(true);
stub_ignore_b.SetVisible(false);
Manage();
EXPECT_TRUE(IsAllocationHibernatedForSurfaceYes(stub1.allocation_));
EXPECT_TRUE(IsAllocationBackgroundForSurfaceYes(stub2.allocation_));
EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub3.allocation_));
EXPECT_TRUE(IsAllocationBackgroundForSurfaceNo(stub4.allocation_));
stub_ignore_c.SetVisible(true);
stub_ignore_c.SetVisible(false);
Manage();
EXPECT_TRUE(IsAllocationHibernatedForSurfaceYes(stub1.allocation_));
EXPECT_TRUE(IsAllocationHibernatedForSurfaceYes(stub2.allocation_));
EXPECT_TRUE(IsAllocationHibernatedForSurfaceNo(stub3.allocation_));
EXPECT_TRUE(IsAllocationHibernatedForSurfaceNo(stub4.allocation_));
}
TEST_F(GpuMemoryManagerTest, TestUpdateAvailableGpuMemory) {
FakeClient stub1(&memmgr_, GenerateUniqueSurfaceId(), true),
stub2(&memmgr_, GenerateUniqueSurfaceId(), false),
stub3(&memmgr_, GenerateUniqueSurfaceId(), true),
stub4(&memmgr_, GenerateUniqueSurfaceId(), false);
uint64 expected = 400 * 1024 * 1024;
stub1.SetTotalGpuMemory(expected);
stub2.SetTotalGpuMemory(expected - 1024 * 1024);
stub3.SetTotalGpuMemory(expected + 1024 * 1024);
stub4.SetTotalGpuMemory(expected + 1024 * 1024);
Manage();
uint64 bytes_expected = CalcAvailableFromGpuTotal(expected);
EXPECT_EQ(GetAvailableGpuMemory(), CalcAvailableClamped(bytes_expected));
}
TEST_F(GpuMemoryManagerTest, StubMemoryStatsForLastManageTests) {
ClientAssignmentCollector::ClientMemoryStatMap stats;
Manage();
stats = ClientAssignmentCollector::GetClientStatsForLastManage();
EXPECT_EQ(stats.size(), 0ul);
FakeClient stub1(&memmgr_, GenerateUniqueSurfaceId(), true);
Manage();
stats = ClientAssignmentCollector::GetClientStatsForLastManage();
uint64 stub1allocation1 =
stats[&stub1].allocation.bytes_limit_when_visible;
EXPECT_EQ(stats.size(), 1ul);
EXPECT_GT(stub1allocation1, 0ul);
FakeClient stub2(&memmgr_, &stub1);
Manage();
stats = ClientAssignmentCollector::GetClientStatsForLastManage();
EXPECT_EQ(stats.count(&stub1), 1ul);
uint64 stub1allocation2 =
stats[&stub1].allocation.bytes_limit_when_visible;
EXPECT_EQ(stats.count(&stub2), 1ul);
uint64 stub2allocation2 =
stats[&stub2].allocation.bytes_limit_when_visible;
EXPECT_EQ(stats.size(), 2ul);
EXPECT_GT(stub1allocation2, 0ul);
EXPECT_GT(stub2allocation2, 0ul);
if (stub1allocation2 != GetMaximumClientAllocation())
EXPECT_LT(stub1allocation2, stub1allocation1);
FakeClient stub3(&memmgr_, GenerateUniqueSurfaceId(), true);
Manage();
stats = ClientAssignmentCollector::GetClientStatsForLastManage();
uint64 stub1allocation3 =
stats[&stub1].allocation.bytes_limit_when_visible;
uint64 stub2allocation3 =
stats[&stub2].allocation.bytes_limit_when_visible;
uint64 stub3allocation3 =
stats[&stub3].allocation.bytes_limit_when_visible;
EXPECT_EQ(stats.size(), 3ul);
EXPECT_GT(stub1allocation3, 0ul);
EXPECT_GT(stub2allocation3, 0ul);
EXPECT_GT(stub3allocation3, 0ul);
if (stub1allocation3 != GetMaximumClientAllocation())
EXPECT_LT(stub1allocation3, stub1allocation2);
stub1.SetVisible(false);
Manage();
stats = ClientAssignmentCollector::GetClientStatsForLastManage();
uint64 stub1allocation4 =
stats[&stub1].allocation.bytes_limit_when_visible;
uint64 stub2allocation4 =
stats[&stub2].allocation.bytes_limit_when_visible;
uint64 stub3allocation4 =
stats[&stub3].allocation.bytes_limit_when_visible;
EXPECT_EQ(stats.size(), 3ul);
EXPECT_GT(stub1allocation4, 0ul);
EXPECT_GE(stub2allocation4, 0ul);
EXPECT_GT(stub3allocation4, 0ul);
if (stub3allocation3 != GetMaximumClientAllocation())
EXPECT_GT(stub3allocation4, stub3allocation3);
}
TEST_F(GpuMemoryManagerTest, UnmanagedTracking) {
memmgr_.TestingSetAvailableGpuMemory(64);
memmgr_.TestingSetMinimumClientAllocation(8);
memmgr_.TestingSetUnmanagedLimitStep(16);
FakeClient stub1(&memmgr_, GenerateUniqueSurfaceId(), true);
SetClientStats(&stub1, 16, 32);
Manage();
EXPECT_GE(stub1.BytesWhenVisible(), 32u);
memmgr_.TrackMemoryAllocatedChange(
stub1.tracking_group_.get(),
0,
48,
gpu::gles2::MemoryTracker::kUnmanaged);
Manage();
EXPECT_LT(stub1.BytesWhenVisible(), 24u);
memmgr_.TrackMemoryAllocatedChange(
stub1.tracking_group_.get(),
48,
64,
gpu::gles2::MemoryTracker::kUnmanaged);
Manage();
EXPECT_EQ(stub1.BytesWhenVisible(), 8u);
memmgr_.TrackMemoryAllocatedChange(
stub1.tracking_group_.get(),
64,
999,
gpu::gles2::MemoryTracker::kUnmanaged);
Manage();
EXPECT_EQ(stub1.BytesWhenVisible(), 8u);
memmgr_.TrackMemoryAllocatedChange(
stub1.tracking_group_.get(),
999,
0,
gpu::gles2::MemoryTracker::kUnmanaged);
}
TEST_F(GpuMemoryManagerTest, DefaultAllocation) {
memmgr_.TestingSetAvailableGpuMemory(64);
memmgr_.TestingSetMinimumClientAllocation(8);
memmgr_.TestingSetDefaultClientAllocation(16);
FakeClient stub1(&memmgr_, GenerateUniqueSurfaceId(), true);
Manage();
EXPECT_GE(stub1.BytesWhenVisible(),
memmgr_.GetDefaultClientAllocation());
}
}