Commit 830cb220 authored by ericrk's avatar ericrk Committed by Commit bot

cc::ResourcePool - Re-use larger resources for smaller requests

Allows cc::ResourcePool to re-use larger resources to fulfill a smaller
request. This avoids expensive allocations, and is especially useful in
cases where layer sizes are changing due to animation.

Also extends the timeout for resource expiration from 1s to 5s, which
will also cut down on resource allocations.

CQ_INCLUDE_TRYBOTS=master.tryserver.blink:linux_trusty_blink_rel

Review-Url: https://codereview.chromium.org/2726263003
Cr-Commit-Position: refs/heads/master@{#456202}
parent 98567213
...@@ -24,8 +24,35 @@ using base::trace_event::MemoryAllocatorDump; ...@@ -24,8 +24,35 @@ using base::trace_event::MemoryAllocatorDump;
using base::trace_event::MemoryDumpLevelOfDetail; using base::trace_event::MemoryDumpLevelOfDetail;
namespace cc { namespace cc {
namespace {
bool ResourceMeetsSizeRequirements(const gfx::Size& requested_size,
const gfx::Size& actual_size) {
const float kReuseThreshold = 2.0f;
// Allocating new resources is expensive, and we'd like to re-use our
// existing ones within reason. Allow a larger resource to be used for a
// smaller request.
if (actual_size.width() < requested_size.width() ||
actual_size.height() < requested_size.height())
return false;
// GetArea will crash on overflow, however all sizes in use are tile sizes.
// These are capped at ResourceProvider::max_texture_size(), and will not
// overflow.
float actual_area = actual_size.GetArea();
float requested_area = requested_size.GetArea();
// Don't use a resource that is more than |kReuseThreshold| times the
// requested pixel area, as we want to free unnecessarily large resources.
if (actual_area / requested_area > kReuseThreshold)
return false;
return true;
}
} // namespace
base::TimeDelta ResourcePool::kDefaultExpirationDelay = base::TimeDelta ResourcePool::kDefaultExpirationDelay =
base::TimeDelta::FromSeconds(1); base::TimeDelta::FromSeconds(5);
void ResourcePool::PoolResource::OnMemoryDump( void ResourcePool::PoolResource::OnMemoryDump(
base::trace_event::ProcessMemoryDump* pmd, base::trace_event::ProcessMemoryDump* pmd,
...@@ -119,7 +146,7 @@ Resource* ResourcePool::ReuseResource(const gfx::Size& size, ...@@ -119,7 +146,7 @@ Resource* ResourcePool::ReuseResource(const gfx::Size& size,
if (resource->format() != format) if (resource->format() != format)
continue; continue;
if (resource->size() != size) if (!ResourceMeetsSizeRequirements(size, resource->size()))
continue; continue;
if (resource->color_space() != color_space) if (resource->color_space() != color_space)
continue; continue;
......
...@@ -33,6 +33,12 @@ class ResourcePoolTest : public testing::Test { ...@@ -33,6 +33,12 @@ class ResourcePoolTest : public testing::Test {
} }
protected: protected:
void CheckAndReturnResource(Resource* resource) {
EXPECT_NE(nullptr, resource);
resource_pool_->ReleaseResource(resource);
resource_pool_->CheckBusyResources();
}
scoped_refptr<TestContextProvider> context_provider_; scoped_refptr<TestContextProvider> context_provider_;
std::unique_ptr<SharedBitmapManager> shared_bitmap_manager_; std::unique_ptr<SharedBitmapManager> shared_bitmap_manager_;
std::unique_ptr<ResourceProvider> resource_provider_; std::unique_ptr<ResourceProvider> resource_provider_;
...@@ -105,32 +111,28 @@ TEST_F(ResourcePoolTest, SimpleResourceReuse) { ...@@ -105,32 +111,28 @@ TEST_F(ResourcePoolTest, SimpleResourceReuse) {
gfx::ColorSpace color_space1; gfx::ColorSpace color_space1;
gfx::ColorSpace color_space2 = gfx::ColorSpace::CreateSRGB(); gfx::ColorSpace color_space2 = gfx::ColorSpace::CreateSRGB();
Resource* resource = CheckAndReturnResource(
resource_pool_->AcquireResource(size, format, color_space1); resource_pool_->AcquireResource(size, format, color_space1));
resource_pool_->ReleaseResource(resource);
resource_pool_->CheckBusyResources();
EXPECT_EQ(1u, resource_provider_->num_resources()); EXPECT_EQ(1u, resource_provider_->num_resources());
// Same size/format should re-use resource. // Same size/format should re-use resource.
resource = resource_pool_->AcquireResource(size, format, color_space1); Resource* resource =
resource_pool_->AcquireResource(size, format, color_space1);
EXPECT_EQ(1u, resource_provider_->num_resources()); EXPECT_EQ(1u, resource_provider_->num_resources());
resource_pool_->ReleaseResource(resource); CheckAndReturnResource(resource);
resource_pool_->CheckBusyResources();
EXPECT_EQ(1u, resource_provider_->num_resources()); EXPECT_EQ(1u, resource_provider_->num_resources());
// Different size/format should allocate new resource. // Different size/format should allocate new resource.
resource = resource_pool_->AcquireResource(gfx::Size(50, 50), LUMINANCE_8, resource = resource_pool_->AcquireResource(gfx::Size(50, 50), LUMINANCE_8,
color_space1); color_space1);
EXPECT_EQ(2u, resource_provider_->num_resources()); EXPECT_EQ(2u, resource_provider_->num_resources());
resource_pool_->ReleaseResource(resource); CheckAndReturnResource(resource);
resource_pool_->CheckBusyResources();
EXPECT_EQ(2u, resource_provider_->num_resources()); EXPECT_EQ(2u, resource_provider_->num_resources());
// Different color space should allocate new resource. // Different color space should allocate new resource.
resource = resource_pool_->AcquireResource(size, format, color_space2); resource = resource_pool_->AcquireResource(size, format, color_space2);
EXPECT_EQ(3u, resource_provider_->num_resources()); EXPECT_EQ(3u, resource_provider_->num_resources());
resource_pool_->ReleaseResource(resource); CheckAndReturnResource(resource);
resource_pool_->CheckBusyResources();
EXPECT_EQ(3u, resource_provider_->num_resources()); EXPECT_EQ(3u, resource_provider_->num_resources());
} }
...@@ -317,25 +319,47 @@ TEST_F(ResourcePoolTest, ReuseResource) { ...@@ -317,25 +319,47 @@ TEST_F(ResourcePoolTest, ReuseResource) {
ResourceFormat format = RGBA_8888; ResourceFormat format = RGBA_8888;
gfx::ColorSpace color_space = gfx::ColorSpace::CreateSRGB(); gfx::ColorSpace color_space = gfx::ColorSpace::CreateSRGB();
// Create unused resources with sizes close to 100, 100. // Create unused resource with size 100x100.
resource_pool_->ReleaseResource( CheckAndReturnResource(
resource_pool_->CreateResource(gfx::Size(99, 100), format, color_space)); resource_pool_->CreateResource(gfx::Size(100, 100), format, color_space));
resource_pool_->ReleaseResource(
resource_pool_->CreateResource(gfx::Size(99, 99), format, color_space)); // Try some cases that are too large, none should succeed.
resource_pool_->ReleaseResource( EXPECT_EQ(nullptr, resource_pool_->ReuseResource(gfx::Size(101, 100), format,
resource_pool_->CreateResource(gfx::Size(100, 99), format, color_space)); color_space));
resource_pool_->ReleaseResource( EXPECT_EQ(nullptr, resource_pool_->ReuseResource(gfx::Size(100, 101), format,
resource_pool_->CreateResource(gfx::Size(101, 101), format, color_space)); color_space));
resource_pool_->CheckBusyResources(); EXPECT_EQ(nullptr, resource_pool_->ReuseResource(gfx::Size(90, 120), format,
color_space));
gfx::Size size(100, 100); EXPECT_EQ(nullptr, resource_pool_->ReuseResource(gfx::Size(120, 120), format,
Resource* resource = resource_pool_->ReuseResource(size, format, color_space); color_space));
EXPECT_EQ(nullptr, resource);
size = gfx::Size(100, 99); // Try some cases that are more than 2x smaller than 100x100 in area and
resource = resource_pool_->ReuseResource(size, format, color_space); // won't be re-used.
EXPECT_NE(nullptr, resource); EXPECT_EQ(nullptr, resource_pool_->ReuseResource(gfx::Size(49, 100), format,
ASSERT_EQ(nullptr, resource_pool_->ReuseResource(size, format, color_space)); color_space));
resource_pool_->ReleaseResource(resource); EXPECT_EQ(nullptr, resource_pool_->ReuseResource(gfx::Size(100, 49), format,
color_space));
EXPECT_EQ(nullptr, resource_pool_->ReuseResource(gfx::Size(50, 50), format,
color_space));
EXPECT_EQ(nullptr, resource_pool_->ReuseResource(gfx::Size(70, 70), format,
color_space));
// Try some cases that are smaller than 100x100, but within 2x area. Reuse
// should succeed.
CheckAndReturnResource(
resource_pool_->ReuseResource(gfx::Size(50, 100), format, color_space));
CheckAndReturnResource(
resource_pool_->ReuseResource(gfx::Size(100, 50), format, color_space));
CheckAndReturnResource(
resource_pool_->ReuseResource(gfx::Size(71, 71), format, color_space));
// 100x100 is an exact match and should succeed. A subsequent request for
// the same size should fail (the resource is already in use).
Resource* resource =
resource_pool_->ReuseResource(gfx::Size(100, 100), format, color_space);
EXPECT_EQ(nullptr, resource_pool_->ReuseResource(gfx::Size(100, 100), format,
color_space));
CheckAndReturnResource(resource);
} }
TEST_F(ResourcePoolTest, MemoryStateSuspended) { TEST_F(ResourcePoolTest, MemoryStateSuspended) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment