12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/resources/resource_pool.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/resources/resource_provider.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace cc { 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ResourcePool::Resource::Resource(cc::ResourceProvider* resource_provider, 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gfx::Size size, 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GLenum format) 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : cc::Resource(resource_provider->CreateManagedResource( 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size, 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) format, 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ResourceProvider::TextureUsageAny), 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size, 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) format), 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) resource_provider_(resource_provider) { 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(id()); 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ResourcePool::Resource::~Resource() { 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(id()); 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(resource_provider_); 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) resource_provider_->DeleteResource(id()); 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ResourcePool::ResourcePool(ResourceProvider* resource_provider) 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : resource_provider_(resource_provider), 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) max_memory_usage_bytes_(0), 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) max_unused_memory_usage_bytes_(0), 34f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles) max_resource_count_(0), 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) memory_usage_bytes_(0), 36a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) unused_memory_usage_bytes_(0), 37f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles) resource_count_(0) { 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ResourcePool::~ResourcePool() { 41f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles) SetResourceUsageLimits(0, 0, 0); 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_ptr<ResourcePool::Resource> ResourcePool::AcquireResource( 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gfx::Size size, GLenum format) { 46f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles) for (ResourceList::iterator it = unused_resources_.begin(); 47f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles) it != unused_resources_.end(); ++it) { 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Resource* resource = *it; 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(epenner): It would be nice to DCHECK that this 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // doesn't happen two frames in a row for any resource 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // in this pool. 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!resource_provider_->CanLockForWrite(resource->id())) 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (resource->size() != size) 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (resource->format() != format) 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 61f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles) unused_resources_.erase(it); 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) unused_memory_usage_bytes_ -= resource->bytes(); 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return make_scoped_ptr(resource); 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create new resource. 67f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles) Resource* resource = new Resource(resource_provider_, size, format); 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Extend all read locks on all resources until the resource is 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // finished being used, such that we know when resources are 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // truly safe to recycle. 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) resource_provider_->EnableReadLockFences(resource->id(), true); 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) memory_usage_bytes_ += resource->bytes(); 75f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles) ++resource_count_; 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return make_scoped_ptr(resource); 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ResourcePool::ReleaseResource( 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<ResourcePool::Resource> resource) { 81f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles) if (ResourceUsageTooHigh()) { 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) memory_usage_bytes_ -= resource->bytes(); 83f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles) --resource_count_; 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) unused_memory_usage_bytes_ += resource->bytes(); 88f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles) unused_resources_.push_back(resource.release()); 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 91f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles)void ResourcePool::SetResourceUsageLimits( 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) size_t max_memory_usage_bytes, 93a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) size_t max_unused_memory_usage_bytes, 94f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles) size_t max_resource_count) { 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) max_memory_usage_bytes_ = max_memory_usage_bytes; 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) max_unused_memory_usage_bytes_ = max_unused_memory_usage_bytes; 97f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles) max_resource_count_ = max_resource_count; 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 99f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles) ReduceResourceUsage(); 100f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles)} 101f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles) 102f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles)void ResourcePool::ReduceResourceUsage() { 103f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles) while (!unused_resources_.empty()) { 104f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles) if (!ResourceUsageTooHigh()) 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // MRU eviction pattern as least recently used is less likely to 108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // be blocked by read lock fence. 109f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles) Resource* resource = unused_resources_.back(); 110f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles) unused_resources_.pop_back(); 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) memory_usage_bytes_ -= resource->bytes(); 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) unused_memory_usage_bytes_ -= resource->bytes(); 113f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles) --resource_count_; 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete resource; 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 118f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles)bool ResourcePool::ResourceUsageTooHigh() { 119f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles) if (resource_count_ > max_resource_count_) 120a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return true; 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (memory_usage_bytes_ > max_memory_usage_bytes_) 122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return true; 123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (unused_memory_usage_bytes_ > max_unused_memory_usage_bytes_) 124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return true; 125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace cc 129