summaryrefslogtreecommitdiff
path: root/chromium/cc/resources/resource_pool.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/cc/resources/resource_pool.cc')
-rw-r--r--chromium/cc/resources/resource_pool.cc121
1 files changed, 121 insertions, 0 deletions
diff --git a/chromium/cc/resources/resource_pool.cc b/chromium/cc/resources/resource_pool.cc
new file mode 100644
index 00000000000..5835db565d3
--- /dev/null
+++ b/chromium/cc/resources/resource_pool.cc
@@ -0,0 +1,121 @@
+// Copyright 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 "cc/resources/resource_pool.h"
+
+#include "cc/resources/resource_provider.h"
+
+namespace cc {
+
+ResourcePool::Resource::Resource(cc::ResourceProvider* resource_provider,
+ gfx::Size size,
+ GLenum format)
+ : cc::Resource(resource_provider->CreateManagedResource(
+ size,
+ format,
+ ResourceProvider::TextureUsageAny),
+ size,
+ format),
+ resource_provider_(resource_provider) {
+ DCHECK(id());
+}
+
+ResourcePool::Resource::~Resource() {
+ DCHECK(id());
+ DCHECK(resource_provider_);
+ resource_provider_->DeleteResource(id());
+}
+
+ResourcePool::ResourcePool(ResourceProvider* resource_provider)
+ : resource_provider_(resource_provider),
+ max_memory_usage_bytes_(0),
+ max_unused_memory_usage_bytes_(0),
+ memory_usage_bytes_(0),
+ unused_memory_usage_bytes_(0),
+ num_resources_limit_(0) {
+}
+
+ResourcePool::~ResourcePool() {
+ SetMemoryUsageLimits(0, 0, 0);
+}
+
+scoped_ptr<ResourcePool::Resource> ResourcePool::AcquireResource(
+ gfx::Size size, GLenum format) {
+ for (ResourceList::iterator it = resources_.begin();
+ it != resources_.end(); ++it) {
+ Resource* resource = *it;
+
+ // TODO(epenner): It would be nice to DCHECK that this
+ // doesn't happen two frames in a row for any resource
+ // in this pool.
+ if (!resource_provider_->CanLockForWrite(resource->id()))
+ continue;
+
+ if (resource->size() != size)
+ continue;
+ if (resource->format() != format)
+ continue;
+
+ resources_.erase(it);
+ unused_memory_usage_bytes_ -= resource->bytes();
+ return make_scoped_ptr(resource);
+ }
+
+ // Create new resource.
+ Resource* resource = new Resource(
+ resource_provider_, size, format);
+
+ // Extend all read locks on all resources until the resource is
+ // finished being used, such that we know when resources are
+ // truly safe to recycle.
+ resource_provider_->EnableReadLockFences(resource->id(), true);
+
+ memory_usage_bytes_ += resource->bytes();
+ return make_scoped_ptr(resource);
+}
+
+void ResourcePool::ReleaseResource(
+ scoped_ptr<ResourcePool::Resource> resource) {
+ if (MemoryUsageTooHigh()) {
+ memory_usage_bytes_ -= resource->bytes();
+ return;
+ }
+
+ unused_memory_usage_bytes_ += resource->bytes();
+ resources_.push_back(resource.release());
+}
+
+void ResourcePool::SetMemoryUsageLimits(
+ size_t max_memory_usage_bytes,
+ size_t max_unused_memory_usage_bytes,
+ size_t num_resources_limit) {
+ max_memory_usage_bytes_ = max_memory_usage_bytes;
+ max_unused_memory_usage_bytes_ = max_unused_memory_usage_bytes;
+ num_resources_limit_ = num_resources_limit;
+
+ while (!resources_.empty()) {
+ if (!MemoryUsageTooHigh())
+ break;
+
+ // MRU eviction pattern as least recently used is less likely to
+ // be blocked by read lock fence.
+ Resource* resource = resources_.back();
+ resources_.pop_back();
+ memory_usage_bytes_ -= resource->bytes();
+ unused_memory_usage_bytes_ -= resource->bytes();
+ delete resource;
+ }
+}
+
+bool ResourcePool::MemoryUsageTooHigh() {
+ if (resources_.size() > num_resources_limit_)
+ return true;
+ if (memory_usage_bytes_ > max_memory_usage_bytes_)
+ return true;
+ if (unused_memory_usage_bytes_ > max_unused_memory_usage_bytes_)
+ return true;
+ return false;
+}
+
+} // namespace cc