This source file includes following definitions.
- output_surface_
- TexturesMemorySize
- CreateManager
- ValidateTexture
- PrioritizeTexturesAndBackings
- ResourceManagerUpdateBackingsPriorities
- resource_provider
- ResourceManagerAssertInvariants
- TextureBackingIsAbovePriorityCutoff
- EvictedBackingCount
- BackingResources
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
#include "cc/resources/prioritized_resource.h"
#include <vector>
#include "cc/resources/prioritized_resource_manager.h"
#include "cc/resources/resource.h"
#include "cc/resources/resource_provider.h"
#include "cc/test/fake_output_surface.h"
#include "cc/test/fake_output_surface_client.h"
#include "cc/test/fake_proxy.h"
#include "cc/test/test_shared_bitmap_manager.h"
#include "cc/test/tiled_layer_test_common.h"
#include "cc/trees/single_thread_proxy.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace cc {
class PrioritizedResourceTest : public testing::Test {
public:
PrioritizedResourceTest()
: texture_size_(256, 256),
texture_format_(RGBA_8888),
output_surface_(FakeOutputSurface::Create3d()) {
DebugScopedSetImplThread impl_thread(&proxy_);
CHECK(output_surface_->BindToClient(&output_surface_client_));
shared_bitmap_manager_.reset(new TestSharedBitmapManager());
resource_provider_ = ResourceProvider::Create(
output_surface_.get(), shared_bitmap_manager_.get(), 0, false, 1);
}
virtual ~PrioritizedResourceTest() {
DebugScopedSetImplThread impl_thread(&proxy_);
resource_provider_.reset();
}
size_t TexturesMemorySize(size_t texture_count) {
return Resource::MemorySizeBytes(texture_size_, texture_format_) *
texture_count;
}
scoped_ptr<PrioritizedResourceManager> CreateManager(size_t max_textures) {
scoped_ptr<PrioritizedResourceManager> manager =
PrioritizedResourceManager::Create(&proxy_);
manager->SetMaxMemoryLimitBytes(TexturesMemorySize(max_textures));
return manager.Pass();
}
bool ValidateTexture(PrioritizedResource* texture,
bool request_late) {
ResourceManagerAssertInvariants(texture->resource_manager());
if (request_late)
texture->RequestLate();
ResourceManagerAssertInvariants(texture->resource_manager());
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
bool success = texture->can_acquire_backing_texture();
if (success)
texture->AcquireBackingTexture(resource_provider());
return success;
}
void PrioritizeTexturesAndBackings(
PrioritizedResourceManager* resource_manager) {
resource_manager->PrioritizeTextures();
ResourceManagerUpdateBackingsPriorities(resource_manager);
}
void ResourceManagerUpdateBackingsPriorities(
PrioritizedResourceManager* resource_manager) {
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
resource_manager->PushTexturePrioritiesToBackings();
}
ResourceProvider* resource_provider() { return resource_provider_.get(); }
void ResourceManagerAssertInvariants(
PrioritizedResourceManager* resource_manager) {
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
resource_manager->AssertInvariants();
}
bool TextureBackingIsAbovePriorityCutoff(PrioritizedResource* texture) {
return texture->backing()->
was_above_priority_cutoff_at_last_priority_update();
}
size_t EvictedBackingCount(PrioritizedResourceManager* resource_manager) {
return resource_manager->evicted_backings_.size();
}
std::vector<unsigned> BackingResources(
PrioritizedResourceManager* resource_manager) {
std::vector<unsigned> resources;
for (PrioritizedResourceManager::BackingList::iterator it =
resource_manager->backings_.begin();
it != resource_manager->backings_.end();
++it)
resources.push_back((*it)->id());
return resources;
}
protected:
FakeProxy proxy_;
const gfx::Size texture_size_;
const ResourceFormat texture_format_;
FakeOutputSurfaceClient output_surface_client_;
scoped_ptr<OutputSurface> output_surface_;
scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
scoped_ptr<ResourceProvider> resource_provider_;
};
namespace {
TEST_F(PrioritizedResourceTest, RequestTextureExceedingMaxLimit) {
const size_t kMaxTextures = 8;
scoped_ptr<PrioritizedResourceManager> resource_manager =
CreateManager(kMaxTextures);
scoped_ptr<PrioritizedResource> textures[kMaxTextures * 2];
for (size_t i = 0; i < kMaxTextures * 2; ++i)
textures[i] =
resource_manager->CreateTexture(texture_size_, texture_format_);
for (size_t i = 0; i < kMaxTextures * 2; ++i)
textures[i]->set_request_priority(100 + i);
PrioritizeTexturesAndBackings(resource_manager.get());
EXPECT_TRUE(ValidateTexture(textures[0].get(), false));
EXPECT_TRUE(ValidateTexture(textures[7].get(), false));
EXPECT_FALSE(ValidateTexture(textures[8].get(), false));
EXPECT_FALSE(ValidateTexture(textures[15].get(), false));
for (size_t i = 0; i < kMaxTextures * 2; ++i)
textures[i]->set_request_priority(100 - i);
PrioritizeTexturesAndBackings(resource_manager.get());
EXPECT_FALSE(ValidateTexture(textures[0].get(), false));
EXPECT_FALSE(ValidateTexture(textures[7].get(), false));
EXPECT_TRUE(ValidateTexture(textures[8].get(), false));
EXPECT_TRUE(ValidateTexture(textures[15].get(), false));
EXPECT_EQ(TexturesMemorySize(kMaxTextures),
resource_manager->MemoryAboveCutoffBytes());
EXPECT_LE(resource_manager->MemoryUseBytes(),
resource_manager->MemoryAboveCutoffBytes());
EXPECT_EQ(TexturesMemorySize(2*kMaxTextures),
resource_manager->MaxMemoryNeededBytes());
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
resource_manager->ClearAllMemory(resource_provider());
}
TEST_F(PrioritizedResourceTest, ChangeMemoryLimits) {
const size_t kMaxTextures = 8;
scoped_ptr<PrioritizedResourceManager> resource_manager =
CreateManager(kMaxTextures);
scoped_ptr<PrioritizedResource> textures[kMaxTextures];
for (size_t i = 0; i < kMaxTextures; ++i) {
textures[i] =
resource_manager->CreateTexture(texture_size_, texture_format_);
}
for (size_t i = 0; i < kMaxTextures; ++i)
textures[i]->set_request_priority(100 + i);
resource_manager->SetMaxMemoryLimitBytes(TexturesMemorySize(8));
PrioritizeTexturesAndBackings(resource_manager.get());
for (size_t i = 0; i < kMaxTextures; ++i)
ValidateTexture(textures[i].get(), false);
{
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
resource_manager->ReduceMemory(resource_provider());
}
EXPECT_EQ(TexturesMemorySize(8), resource_manager->MemoryAboveCutoffBytes());
EXPECT_LE(resource_manager->MemoryUseBytes(),
resource_manager->MemoryAboveCutoffBytes());
resource_manager->SetMaxMemoryLimitBytes(TexturesMemorySize(5));
PrioritizeTexturesAndBackings(resource_manager.get());
for (size_t i = 0; i < kMaxTextures; ++i)
EXPECT_EQ(ValidateTexture(textures[i].get(), false), i < 5);
{
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
resource_manager->ReduceMemory(resource_provider());
}
EXPECT_EQ(TexturesMemorySize(5), resource_manager->MemoryAboveCutoffBytes());
EXPECT_LE(resource_manager->MemoryUseBytes(),
resource_manager->MemoryAboveCutoffBytes());
EXPECT_EQ(TexturesMemorySize(kMaxTextures),
resource_manager->MaxMemoryNeededBytes());
resource_manager->SetMaxMemoryLimitBytes(TexturesMemorySize(4));
PrioritizeTexturesAndBackings(resource_manager.get());
for (size_t i = 0; i < kMaxTextures; ++i)
EXPECT_EQ(ValidateTexture(textures[i].get(), false), i < 4);
{
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
resource_manager->ReduceMemory(resource_provider());
}
EXPECT_EQ(TexturesMemorySize(4), resource_manager->MemoryAboveCutoffBytes());
EXPECT_LE(resource_manager->MemoryUseBytes(),
resource_manager->MemoryAboveCutoffBytes());
EXPECT_EQ(TexturesMemorySize(kMaxTextures),
resource_manager->MaxMemoryNeededBytes());
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
resource_manager->ClearAllMemory(resource_provider());
}
TEST_F(PrioritizedResourceTest, ReduceWastedMemory) {
const size_t kMaxTextures = 20;
scoped_ptr<PrioritizedResourceManager> resource_manager =
CreateManager(kMaxTextures);
scoped_ptr<PrioritizedResource> textures[kMaxTextures];
for (size_t i = 0; i < kMaxTextures; ++i) {
textures[i] =
resource_manager->CreateTexture(texture_size_, texture_format_);
}
for (size_t i = 0; i < kMaxTextures; ++i)
textures[i]->set_request_priority(100 + i);
resource_manager->SetMaxMemoryLimitBytes(TexturesMemorySize(kMaxTextures));
PrioritizeTexturesAndBackings(resource_manager.get());
for (size_t i = 0; i < kMaxTextures; ++i) {
ValidateTexture(textures[i].get(), false);
{
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
uint8_t image[4] = {0};
textures[i]->SetPixels(resource_provider_.get(),
image,
gfx::Rect(1, 1),
gfx::Rect(1, 1),
gfx::Vector2d());
}
}
{
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
resource_manager->ReduceMemory(resource_provider());
}
EXPECT_EQ(TexturesMemorySize(20), resource_manager->MemoryUseBytes());
textures[0] = scoped_ptr<PrioritizedResource>();
PrioritizeTexturesAndBackings(resource_manager.get());
{
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
resource_manager->UpdateBackingsState(resource_provider());
resource_manager->ReduceWastedMemory(resource_provider());
}
EXPECT_EQ(TexturesMemorySize(20), resource_manager->MemoryUseBytes());
for (size_t i = 0; i < kMaxTextures / 2; ++i)
textures[i] = scoped_ptr<PrioritizedResource>();
PrioritizeTexturesAndBackings(resource_manager.get());
{
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
resource_manager->UpdateBackingsState(resource_provider());
resource_manager->ReduceWastedMemory(resource_provider());
}
EXPECT_GT(TexturesMemorySize(20), resource_manager->MemoryUseBytes());
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
resource_manager->ClearAllMemory(resource_provider());
}
TEST_F(PrioritizedResourceTest, InUseNotWastedMemory) {
const size_t kMaxTextures = 20;
scoped_ptr<PrioritizedResourceManager> resource_manager =
CreateManager(kMaxTextures);
scoped_ptr<PrioritizedResource> textures[kMaxTextures];
for (size_t i = 0; i < kMaxTextures; ++i) {
textures[i] =
resource_manager->CreateTexture(texture_size_, texture_format_);
}
for (size_t i = 0; i < kMaxTextures; ++i)
textures[i]->set_request_priority(100 + i);
resource_manager->SetMaxMemoryLimitBytes(TexturesMemorySize(kMaxTextures));
PrioritizeTexturesAndBackings(resource_manager.get());
for (size_t i = 0; i < kMaxTextures; ++i) {
ValidateTexture(textures[i].get(), false);
{
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
uint8_t image[4] = {0};
textures[i]->SetPixels(resource_provider_.get(),
image,
gfx::Rect(1, 1),
gfx::Rect(1, 1),
gfx::Vector2d());
}
}
{
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
resource_manager->ReduceMemory(resource_provider());
}
EXPECT_EQ(TexturesMemorySize(20), resource_manager->MemoryUseBytes());
ResourceProvider::ResourceIdArray to_send;
TransferableResourceArray transferable;
for (size_t i = 0; i < kMaxTextures / 2; ++i)
to_send.push_back(textures[i]->resource_id());
resource_provider_->PrepareSendToParent(to_send, &transferable);
for (size_t i = 0; i < kMaxTextures / 2; ++i)
textures[i] = scoped_ptr<PrioritizedResource>();
PrioritizeTexturesAndBackings(resource_manager.get());
{
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
resource_manager->UpdateBackingsState(resource_provider());
resource_manager->ReduceWastedMemory(resource_provider());
}
EXPECT_EQ(TexturesMemorySize(20), resource_manager->MemoryUseBytes());
ReturnedResourceArray returns;
TransferableResource::ReturnResources(transferable, &returns);
resource_provider_->ReceiveReturnsFromParent(returns);
{
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
resource_manager->UpdateBackingsState(resource_provider());
resource_manager->ReduceWastedMemory(resource_provider());
}
EXPECT_GT(TexturesMemorySize(20), resource_manager->MemoryUseBytes());
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
resource_manager->ClearAllMemory(resource_provider());
}
TEST_F(PrioritizedResourceTest, ChangePriorityCutoff) {
const size_t kMaxTextures = 8;
scoped_ptr<PrioritizedResourceManager> resource_manager =
CreateManager(kMaxTextures);
scoped_ptr<PrioritizedResource> textures[kMaxTextures];
for (size_t i = 0; i < kMaxTextures; ++i) {
textures[i] =
resource_manager->CreateTexture(texture_size_, texture_format_);
}
for (size_t i = 0; i < kMaxTextures; ++i)
textures[i]->set_request_priority(100 + i);
resource_manager->SetMaxMemoryLimitBytes(TexturesMemorySize(8));
resource_manager->SetExternalPriorityCutoff(106);
PrioritizeTexturesAndBackings(resource_manager.get());
for (size_t i = 0; i < kMaxTextures; ++i)
EXPECT_EQ(ValidateTexture(textures[i].get(), true), i < 6);
{
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
resource_manager->ReduceMemory(resource_provider());
}
EXPECT_EQ(TexturesMemorySize(6), resource_manager->MemoryAboveCutoffBytes());
EXPECT_LE(resource_manager->MemoryUseBytes(),
resource_manager->MemoryAboveCutoffBytes());
resource_manager->SetExternalPriorityCutoff(104);
PrioritizeTexturesAndBackings(resource_manager.get());
for (size_t i = 0; i < kMaxTextures; ++i)
EXPECT_EQ(ValidateTexture(textures[i].get(), false), i < 4);
{
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
resource_manager->ReduceMemory(resource_provider());
}
EXPECT_EQ(TexturesMemorySize(4), resource_manager->MemoryAboveCutoffBytes());
resource_manager->UnlinkAndClearEvictedBackings();
{
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
resource_manager->ReduceMemoryOnImplThread(
TexturesMemorySize(8), 104, resource_provider());
EXPECT_EQ(0u, EvictedBackingCount(resource_manager.get()));
resource_manager->ReduceMemoryOnImplThread(
TexturesMemorySize(8), 103, resource_provider());
EXPECT_EQ(1u, EvictedBackingCount(resource_manager.get()));
}
resource_manager->UnlinkAndClearEvictedBackings();
EXPECT_EQ(TexturesMemorySize(3), resource_manager->MemoryUseBytes());
PrioritizeTexturesAndBackings(resource_manager.get());
for (size_t i = 0; i < kMaxTextures; ++i)
EXPECT_EQ(ValidateTexture(textures[i].get(), false), i < 4);
{
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
resource_manager->ReduceMemory(resource_provider());
}
EXPECT_EQ(TexturesMemorySize(4), resource_manager->MemoryAboveCutoffBytes());
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
resource_manager->ClearAllMemory(resource_provider());
}
TEST_F(PrioritizedResourceTest, EvictingTexturesInParent) {
const size_t kMaxTextures = 8;
scoped_ptr<PrioritizedResourceManager> resource_manager =
CreateManager(kMaxTextures);
scoped_ptr<PrioritizedResource> textures[kMaxTextures];
unsigned texture_resource_ids[kMaxTextures];
for (size_t i = 0; i < kMaxTextures; ++i) {
textures[i] =
resource_manager->CreateTexture(texture_size_, texture_format_);
textures[i]->set_request_priority(100 + i);
}
PrioritizeTexturesAndBackings(resource_manager.get());
for (size_t i = 0; i < kMaxTextures; ++i) {
EXPECT_TRUE(ValidateTexture(textures[i].get(), true));
{
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
uint8_t image[4] = {0};
textures[i]->SetPixels(resource_provider_.get(),
image,
gfx::Rect(1, 1),
gfx::Rect(1, 1),
gfx::Vector2d());
}
}
{
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
resource_manager->ReduceMemory(resource_provider());
}
EXPECT_EQ(TexturesMemorySize(8), resource_manager->MemoryAboveCutoffBytes());
for (size_t i = 0; i < 8; ++i)
texture_resource_ids[i] = textures[i]->resource_id();
{
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
resource_manager->ReduceMemoryOnImplThread(
TexturesMemorySize(4), 200, resource_provider());
EXPECT_EQ(4u, EvictedBackingCount(resource_manager.get()));
std::vector<unsigned> remaining = BackingResources(resource_manager.get());
EXPECT_TRUE(std::find(remaining.begin(),
remaining.end(),
texture_resource_ids[0]) != remaining.end());
EXPECT_TRUE(std::find(remaining.begin(),
remaining.end(),
texture_resource_ids[1]) != remaining.end());
EXPECT_TRUE(std::find(remaining.begin(),
remaining.end(),
texture_resource_ids[2]) != remaining.end());
EXPECT_TRUE(std::find(remaining.begin(),
remaining.end(),
texture_resource_ids[3]) != remaining.end());
}
resource_manager->UnlinkAndClearEvictedBackings();
EXPECT_EQ(TexturesMemorySize(4), resource_manager->MemoryUseBytes());
PrioritizeTexturesAndBackings(resource_manager.get());
for (size_t i = 0; i < kMaxTextures; ++i) {
EXPECT_TRUE(ValidateTexture(textures[i].get(), true));
{
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
uint8_t image[4] = {0};
textures[i]->SetPixels(resource_provider_.get(),
image,
gfx::Rect(1, 1),
gfx::Rect(1, 1),
gfx::Vector2d());
}
}
{
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
resource_manager->ReduceMemory(resource_provider());
}
EXPECT_EQ(TexturesMemorySize(8), resource_manager->MemoryAboveCutoffBytes());
ResourceProvider::ResourceIdArray to_send;
TransferableResourceArray transferable;
for (size_t i = 6; i < 8; ++i)
to_send.push_back(textures[i]->resource_id());
resource_provider_->PrepareSendToParent(to_send, &transferable);
textures[4]->set_request_priority(100 + 4);
textures[5]->set_request_priority(100 + 5);
textures[6]->set_request_priority(100 + 4);
textures[7]->set_request_priority(100 + 5);
for (size_t i = 0; i < 8; ++i)
texture_resource_ids[i] = textures[i]->resource_id();
for (size_t i = 0; i < 8; ++i)
textures[0].reset();
PrioritizeTexturesAndBackings(resource_manager.get());
{
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
resource_manager->UpdateBackingsState(resource_provider());
}
{
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
resource_manager->ReduceMemoryOnImplThread(
TexturesMemorySize(4), 200, resource_provider());
EXPECT_EQ(4u, EvictedBackingCount(resource_manager.get()));
std::vector<unsigned> remaining = BackingResources(resource_manager.get());
EXPECT_TRUE(std::find(remaining.begin(),
remaining.end(),
texture_resource_ids[6]) == remaining.end());
EXPECT_TRUE(std::find(remaining.begin(),
remaining.end(),
texture_resource_ids[7]) == remaining.end());
}
resource_manager->UnlinkAndClearEvictedBackings();
EXPECT_EQ(TexturesMemorySize(4), resource_manager->MemoryUseBytes());
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
resource_manager->ClearAllMemory(resource_provider());
}
TEST_F(PrioritizedResourceTest, ResourceManagerPartialUpdateTextures) {
const size_t kMaxTextures = 4;
const size_t kNumTextures = 4;
scoped_ptr<PrioritizedResourceManager> resource_manager =
CreateManager(kMaxTextures);
scoped_ptr<PrioritizedResource> textures[kNumTextures];
scoped_ptr<PrioritizedResource> more_textures[kNumTextures];
for (size_t i = 0; i < kNumTextures; ++i) {
textures[i] =
resource_manager->CreateTexture(texture_size_, texture_format_);
more_textures[i] =
resource_manager->CreateTexture(texture_size_, texture_format_);
}
for (size_t i = 0; i < kNumTextures; ++i)
textures[i]->set_request_priority(200 + i);
PrioritizeTexturesAndBackings(resource_manager.get());
EXPECT_TRUE(ValidateTexture(textures[0].get(), false));
EXPECT_TRUE(ValidateTexture(textures[1].get(), false));
EXPECT_TRUE(ValidateTexture(textures[2].get(), false));
EXPECT_TRUE(ValidateTexture(textures[3].get(), false));
EXPECT_TRUE(textures[0]->have_backing_texture());
EXPECT_TRUE(textures[1]->have_backing_texture());
EXPECT_TRUE(textures[2]->have_backing_texture());
EXPECT_TRUE(textures[3]->have_backing_texture());
for (size_t i = 0; i < kNumTextures; ++i)
more_textures[i]->set_request_priority(100 + i);
PrioritizeTexturesAndBackings(resource_manager.get());
EXPECT_FALSE(ValidateTexture(textures[0].get(), false));
EXPECT_FALSE(ValidateTexture(textures[1].get(), false));
EXPECT_FALSE(ValidateTexture(textures[2].get(), false));
EXPECT_FALSE(ValidateTexture(textures[3].get(), false));
EXPECT_TRUE(textures[0]->have_backing_texture());
EXPECT_TRUE(textures[1]->have_backing_texture());
EXPECT_TRUE(textures[2]->have_backing_texture());
EXPECT_TRUE(textures[3]->have_backing_texture());
EXPECT_TRUE(ValidateTexture(more_textures[0].get(), false));
EXPECT_TRUE(ValidateTexture(more_textures[1].get(), false));
EXPECT_TRUE(ValidateTexture(more_textures[2].get(), false));
EXPECT_TRUE(ValidateTexture(more_textures[3].get(), false));
EXPECT_FALSE(textures[0]->have_backing_texture());
EXPECT_FALSE(textures[1]->have_backing_texture());
EXPECT_FALSE(textures[2]->have_backing_texture());
EXPECT_FALSE(textures[3]->have_backing_texture());
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
resource_manager->ClearAllMemory(resource_provider());
}
TEST_F(PrioritizedResourceTest, ResourceManagerPrioritiesAreEqual) {
const size_t kMaxTextures = 16;
scoped_ptr<PrioritizedResourceManager> resource_manager =
CreateManager(kMaxTextures);
scoped_ptr<PrioritizedResource> textures[kMaxTextures];
for (size_t i = 0; i < kMaxTextures; ++i) {
textures[i] =
resource_manager->CreateTexture(texture_size_, texture_format_);
}
for (size_t i = 0; i < kMaxTextures; ++i)
textures[i]->set_request_priority(100);
textures[0]->set_request_priority(99);
textures[1]->set_request_priority(99);
resource_manager->SetMaxMemoryLimitBytes(TexturesMemorySize(8));
PrioritizeTexturesAndBackings(resource_manager.get());
for (size_t i = 0; i < 2; ++i)
EXPECT_TRUE(ValidateTexture(textures[i].get(), false));
for (size_t i = 2; i < kMaxTextures; ++i)
EXPECT_FALSE(ValidateTexture(textures[i].get(), false));
EXPECT_EQ(TexturesMemorySize(2), resource_manager->MemoryAboveCutoffBytes());
EXPECT_LE(resource_manager->MemoryUseBytes(),
resource_manager->MemoryAboveCutoffBytes());
for (size_t i = 0; i < 8; i++)
EXPECT_TRUE(ValidateTexture(textures[i].get(), true));
for (size_t i = 9; i < kMaxTextures; i++)
EXPECT_FALSE(ValidateTexture(textures[i].get(), true));
EXPECT_EQ(TexturesMemorySize(8), resource_manager->MemoryAboveCutoffBytes());
EXPECT_LE(resource_manager->MemoryUseBytes(),
resource_manager->MemoryAboveCutoffBytes());
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
resource_manager->ClearAllMemory(resource_provider());
}
TEST_F(PrioritizedResourceTest, ResourceManagerDestroyedFirst) {
scoped_ptr<PrioritizedResourceManager> resource_manager = CreateManager(1);
scoped_ptr<PrioritizedResource> texture =
resource_manager->CreateTexture(texture_size_, texture_format_);
EXPECT_FALSE(texture->have_backing_texture());
texture->set_request_priority(100);
PrioritizeTexturesAndBackings(resource_manager.get());
EXPECT_TRUE(ValidateTexture(texture.get(), false));
EXPECT_TRUE(texture->can_acquire_backing_texture());
EXPECT_TRUE(texture->have_backing_texture());
{
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
resource_manager->ClearAllMemory(resource_provider());
}
resource_manager.reset();
EXPECT_FALSE(texture->can_acquire_backing_texture());
EXPECT_FALSE(texture->have_backing_texture());
}
TEST_F(PrioritizedResourceTest, TextureMovedToNewManager) {
scoped_ptr<PrioritizedResourceManager> resource_manager_one =
CreateManager(1);
scoped_ptr<PrioritizedResourceManager> resource_manager_two =
CreateManager(1);
scoped_ptr<PrioritizedResource> texture =
resource_manager_one->CreateTexture(texture_size_, texture_format_);
EXPECT_FALSE(texture->have_backing_texture());
texture->set_request_priority(100);
PrioritizeTexturesAndBackings(resource_manager_one.get());
EXPECT_TRUE(ValidateTexture(texture.get(), false));
EXPECT_TRUE(texture->can_acquire_backing_texture());
EXPECT_TRUE(texture->have_backing_texture());
texture->SetTextureManager(NULL);
{
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
resource_manager_one->ClearAllMemory(resource_provider());
}
resource_manager_one.reset();
EXPECT_FALSE(texture->can_acquire_backing_texture());
EXPECT_FALSE(texture->have_backing_texture());
texture->SetTextureManager(resource_manager_two.get());
PrioritizeTexturesAndBackings(resource_manager_two.get());
EXPECT_TRUE(ValidateTexture(texture.get(), false));
EXPECT_TRUE(texture->can_acquire_backing_texture());
EXPECT_TRUE(texture->have_backing_texture());
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
resource_manager_two->ClearAllMemory(resource_provider());
}
TEST_F(PrioritizedResourceTest,
RenderSurfacesReduceMemoryAvailableOutsideRootSurface) {
const size_t kMaxTextures = 8;
scoped_ptr<PrioritizedResourceManager> resource_manager =
CreateManager(kMaxTextures);
scoped_ptr<PrioritizedResource> render_surface_place_holder =
resource_manager->CreateTexture(texture_size_, texture_format_);
render_surface_place_holder->SetToSelfManagedMemoryPlaceholder(
TexturesMemorySize(4));
render_surface_place_holder->set_request_priority(
PriorityCalculator::RenderSurfacePriority());
scoped_ptr<PrioritizedResource> textures[kMaxTextures];
for (size_t i = 0; i < kMaxTextures; ++i) {
textures[i] =
resource_manager->CreateTexture(texture_size_, texture_format_);
}
for (size_t i = 0; i < kMaxTextures; ++i)
textures[i]->set_request_priority(100 + i);
PrioritizeTexturesAndBackings(resource_manager.get());
EXPECT_TRUE(ValidateTexture(textures[0].get(), false));
EXPECT_TRUE(ValidateTexture(textures[3].get(), false));
EXPECT_FALSE(ValidateTexture(textures[4].get(), false));
EXPECT_FALSE(ValidateTexture(textures[7].get(), false));
for (size_t i = 0; i < kMaxTextures; ++i)
textures[i]->set_request_priority(100 - i);
PrioritizeTexturesAndBackings(resource_manager.get());
EXPECT_FALSE(ValidateTexture(textures[0].get(), false));
EXPECT_FALSE(ValidateTexture(textures[3].get(), false));
EXPECT_TRUE(ValidateTexture(textures[4].get(), false));
EXPECT_TRUE(ValidateTexture(textures[7].get(), false));
EXPECT_EQ(TexturesMemorySize(4), resource_manager->MemoryAboveCutoffBytes());
EXPECT_EQ(TexturesMemorySize(4),
resource_manager->MemoryForSelfManagedTextures());
EXPECT_LE(resource_manager->MemoryUseBytes(),
resource_manager->MemoryAboveCutoffBytes());
EXPECT_EQ(TexturesMemorySize(8),
resource_manager->MaxMemoryNeededBytes());
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
resource_manager->ClearAllMemory(resource_provider());
}
TEST_F(PrioritizedResourceTest,
RenderSurfacesReduceMemoryAvailableForRequestLate) {
const size_t kMaxTextures = 8;
scoped_ptr<PrioritizedResourceManager> resource_manager =
CreateManager(kMaxTextures);
scoped_ptr<PrioritizedResource> render_surface_place_holder =
resource_manager->CreateTexture(texture_size_, texture_format_);
render_surface_place_holder->SetToSelfManagedMemoryPlaceholder(
TexturesMemorySize(4));
render_surface_place_holder->set_request_priority(
PriorityCalculator::RenderSurfacePriority());
scoped_ptr<PrioritizedResource> textures[kMaxTextures];
for (size_t i = 0; i < kMaxTextures; ++i) {
textures[i] =
resource_manager->CreateTexture(texture_size_, texture_format_);
}
for (size_t i = 0; i < kMaxTextures; ++i)
textures[i]->set_request_priority(100);
PrioritizeTexturesAndBackings(resource_manager.get());
for (unsigned i = 0; i < kMaxTextures; ++i)
EXPECT_FALSE(ValidateTexture(textures[i].get(), false));
for (unsigned i = 0; i < kMaxTextures; i += 2)
EXPECT_TRUE(ValidateTexture(textures[i].get(), true));
for (unsigned i = 1; i < kMaxTextures; i += 2)
EXPECT_FALSE(ValidateTexture(textures[i].get(), true));
EXPECT_EQ(TexturesMemorySize(4), resource_manager->MemoryAboveCutoffBytes());
EXPECT_EQ(TexturesMemorySize(4),
resource_manager->MemoryForSelfManagedTextures());
EXPECT_LE(resource_manager->MemoryUseBytes(),
resource_manager->MemoryAboveCutoffBytes());
EXPECT_EQ(TexturesMemorySize(8),
resource_manager->MaxMemoryNeededBytes());
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
resource_manager->ClearAllMemory(resource_provider());
}
TEST_F(PrioritizedResourceTest,
WhenRenderSurfaceNotAvailableTexturesAlsoNotAvailable) {
const size_t kMaxTextures = 8;
scoped_ptr<PrioritizedResourceManager> resource_manager =
CreateManager(kMaxTextures);
scoped_ptr<PrioritizedResource> render_surface_place_holder =
resource_manager->CreateTexture(texture_size_, texture_format_);
render_surface_place_holder->SetToSelfManagedMemoryPlaceholder(
TexturesMemorySize(4));
render_surface_place_holder->set_request_priority(
PriorityCalculator::RenderSurfacePriority());
scoped_ptr<PrioritizedResource> textures[kMaxTextures];
for (size_t i = 0; i < kMaxTextures; ++i)
textures[i] =
resource_manager->CreateTexture(texture_size_, texture_format_);
for (size_t i = 0; i < 6; ++i) {
textures[i]->
set_request_priority(PriorityCalculator::VisiblePriority(true));
}
for (size_t i = 6; i < 8; ++i) {
textures[i]->
set_request_priority(PriorityCalculator::VisiblePriority(false));
}
PrioritizeTexturesAndBackings(resource_manager.get());
EXPECT_FALSE(ValidateTexture(textures[6].get(), true));
EXPECT_FALSE(ValidateTexture(textures[7].get(), true));
for (size_t i = 0; i < 6; ++i)
EXPECT_TRUE(ValidateTexture(textures[i].get(), false));
EXPECT_EQ(TexturesMemorySize(6), resource_manager->MemoryAboveCutoffBytes());
EXPECT_EQ(TexturesMemorySize(2),
resource_manager->MemoryForSelfManagedTextures());
EXPECT_LE(resource_manager->MemoryUseBytes(),
resource_manager->MemoryAboveCutoffBytes());
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
resource_manager->ClearAllMemory(resource_provider());
}
TEST_F(PrioritizedResourceTest, RequestLateBackingsSorting) {
const size_t kMaxTextures = 8;
scoped_ptr<PrioritizedResourceManager> resource_manager =
CreateManager(kMaxTextures);
resource_manager->SetMaxMemoryLimitBytes(TexturesMemorySize(kMaxTextures));
scoped_ptr<PrioritizedResource> textures[kMaxTextures];
for (size_t i = 0; i < kMaxTextures; ++i)
textures[i] =
resource_manager->CreateTexture(texture_size_, texture_format_);
for (size_t i = 0; i < kMaxTextures; ++i)
textures[i]->set_request_priority(100);
PrioritizeTexturesAndBackings(resource_manager.get());
for (unsigned i = 0; i < kMaxTextures; ++i)
EXPECT_TRUE(ValidateTexture(textures[i].get(), false));
resource_manager->SetMaxMemoryLimitBytes(
TexturesMemorySize(kMaxTextures / 2));
PrioritizeTexturesAndBackings(resource_manager.get());
for (size_t i = 0; i < kMaxTextures; i += 2)
EXPECT_TRUE(textures[i]->RequestLate());
ResourceManagerUpdateBackingsPriorities(resource_manager.get());
ResourceManagerAssertInvariants(resource_manager.get());
for (size_t i = 0; i < kMaxTextures; ++i)
EXPECT_TRUE(textures[i]->have_backing_texture());
for (size_t i = 0; i < kMaxTextures; i += 2)
EXPECT_TRUE(TextureBackingIsAbovePriorityCutoff(textures[i].get()));
for (size_t i = 1; i < kMaxTextures; i += 2)
EXPECT_FALSE(TextureBackingIsAbovePriorityCutoff(textures[i].get()));
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
resource_manager->ClearAllMemory(resource_provider());
}
TEST_F(PrioritizedResourceTest, ClearUploadsToEvictedResources) {
const size_t kMaxTextures = 4;
scoped_ptr<PrioritizedResourceManager> resource_manager =
CreateManager(kMaxTextures);
resource_manager->SetMaxMemoryLimitBytes(TexturesMemorySize(kMaxTextures));
scoped_ptr<PrioritizedResource> textures[kMaxTextures];
for (size_t i = 0; i < kMaxTextures; ++i)
textures[i] =
resource_manager->CreateTexture(texture_size_, texture_format_);
for (size_t i = 0; i < kMaxTextures; ++i)
textures[i]->set_request_priority(100);
PrioritizeTexturesAndBackings(resource_manager.get());
for (unsigned i = 0; i < kMaxTextures; ++i)
EXPECT_TRUE(ValidateTexture(textures[i].get(), false));
ResourceUpdateQueue queue;
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
for (size_t i = 0; i < kMaxTextures; ++i) {
const ResourceUpdate upload = ResourceUpdate::Create(
textures[i].get(), NULL, gfx::Rect(), gfx::Rect(), gfx::Vector2d());
queue.AppendFullUpload(upload);
}
for (size_t i = 0; i < kMaxTextures; ++i)
EXPECT_TRUE(textures[i]->have_backing_texture());
queue.ClearUploadsToEvictedResources();
EXPECT_EQ(4u, queue.FullUploadSize());
resource_manager->ReduceMemoryOnImplThread(
TexturesMemorySize(1),
PriorityCalculator::AllowEverythingCutoff(),
resource_provider());
queue.ClearUploadsToEvictedResources();
EXPECT_EQ(1u, queue.FullUploadSize());
resource_manager->ReduceMemoryOnImplThread(
0, PriorityCalculator::AllowEverythingCutoff(), resource_provider());
queue.ClearUploadsToEvictedResources();
EXPECT_EQ(0u, queue.FullUploadSize());
}
TEST_F(PrioritizedResourceTest, UsageStatistics) {
const size_t kMaxTextures = 5;
scoped_ptr<PrioritizedResourceManager> resource_manager =
CreateManager(kMaxTextures);
scoped_ptr<PrioritizedResource> textures[kMaxTextures];
for (size_t i = 0; i < kMaxTextures; ++i) {
textures[i] =
resource_manager->CreateTexture(texture_size_, texture_format_);
}
textures[0]->
set_request_priority(PriorityCalculator::AllowVisibleOnlyCutoff() - 1);
textures[1]->
set_request_priority(PriorityCalculator::AllowVisibleOnlyCutoff());
textures[2]->set_request_priority(
PriorityCalculator::AllowVisibleAndNearbyCutoff() - 1);
textures[3]->
set_request_priority(PriorityCalculator::AllowVisibleAndNearbyCutoff());
textures[4]->set_request_priority(
PriorityCalculator::AllowVisibleAndNearbyCutoff() + 1);
resource_manager->SetMaxMemoryLimitBytes(TexturesMemorySize(2));
PrioritizeTexturesAndBackings(resource_manager.get());
for (size_t i = 0; i < 2; ++i)
EXPECT_TRUE(ValidateTexture(textures[i].get(), false));
for (size_t i = 2; i < kMaxTextures; ++i)
EXPECT_FALSE(ValidateTexture(textures[i].get(), false));
{
DebugScopedSetImplThread impl_thread(&proxy_);
EXPECT_EQ(TexturesMemorySize(2), resource_manager->MemoryUseBytes());
EXPECT_EQ(TexturesMemorySize(1), resource_manager->MemoryVisibleBytes());
EXPECT_EQ(TexturesMemorySize(3),
resource_manager->MemoryVisibleAndNearbyBytes());
}
textures[0]->
set_request_priority(PriorityCalculator::AllowVisibleOnlyCutoff() - 1);
textures[1]->
set_request_priority(PriorityCalculator::AllowVisibleOnlyCutoff() - 1);
textures[2]->
set_request_priority(PriorityCalculator::AllowVisibleOnlyCutoff() - 1);
textures[3]->set_request_priority(
PriorityCalculator::AllowVisibleAndNearbyCutoff() - 1);
textures[4]->
set_request_priority(PriorityCalculator::AllowVisibleAndNearbyCutoff());
resource_manager->PrioritizeTextures();
{
DebugScopedSetImplThread impl_thread(&proxy_);
EXPECT_EQ(TexturesMemorySize(2), resource_manager->MemoryUseBytes());
EXPECT_EQ(TexturesMemorySize(1), resource_manager->MemoryVisibleBytes());
EXPECT_EQ(TexturesMemorySize(3),
resource_manager->MemoryVisibleAndNearbyBytes());
}
{
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
resource_manager->PushTexturePrioritiesToBackings();
EXPECT_EQ(TexturesMemorySize(2), resource_manager->MemoryUseBytes());
EXPECT_EQ(TexturesMemorySize(3), resource_manager->MemoryVisibleBytes());
EXPECT_EQ(TexturesMemorySize(4),
resource_manager->MemoryVisibleAndNearbyBytes());
}
DebugScopedSetImplThreadAndMainThreadBlocked
impl_thread_and_main_thread_blocked(&proxy_);
resource_manager->ClearAllMemory(resource_provider());
}
}
}