Commit dcd7e26e authored by reveman@chromium.org's avatar reveman@chromium.org

cc: Add basic texture recycling to ResourcePool.

Add enough recycling logic to ResourcePool to eliminate unnecessary
command buffer flushes.

BUG=163430
TEST=manual


Review URL: https://chromiumcodereview.appspot.com/11418299

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@171046 0039d316-1c4b-4281-b951-d872f2087c98
parent 17c9f810
...@@ -8,23 +8,82 @@ ...@@ -8,23 +8,82 @@
namespace cc { namespace cc {
ResourcePool::Resource::Resource(cc::ResourceProvider* resource_provider,
cc::Renderer::ResourcePool pool_id,
const gfx::Size& size,
GLenum format)
: cc::Resource(resource_provider->createResource(
pool_id,
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, ResourcePool::ResourcePool(ResourceProvider* resource_provider,
Renderer::ResourcePool pool_id) Renderer::ResourcePool pool_id)
: resource_provider_(resource_provider), : resource_provider_(resource_provider),
pool_id_(pool_id) { pool_id_(pool_id),
max_memory_usage_bytes_(0),
memory_usage_bytes_(0) {
} }
ResourcePool::~ResourcePool() { ResourcePool::~ResourcePool() {
SetMaxMemoryUsageBytes(0);
} }
ResourceProvider::ResourceId ResourcePool::AcquireResource( scoped_ptr<ResourcePool::Resource> ResourcePool::AcquireResource(
const gfx::Size& size, GLenum format) { const gfx::Size& size, GLenum format) {
return resource_provider_->createResource( for (ResourceList::iterator it = resources_.begin();
pool_id_, size, format, ResourceProvider::TextureUsageAny); it != resources_.end(); ++it) {
Resource* resource = *it;
if (resource->size() != size)
continue;
if (resource->format() != format)
continue;
resources_.erase(it);
return make_scoped_ptr(resource);
}
// Create new resource.
Resource* resource = new Resource(
resource_provider_, pool_id_, size, format);
memory_usage_bytes_ += resource->bytes();
return make_scoped_ptr(resource);
} }
void ResourcePool::ReleaseResource(ResourceProvider::ResourceId resource_id) { void ResourcePool::ReleaseResource(
resource_provider_->deleteResource(resource_id); scoped_ptr<ResourcePool::Resource> resource) {
if (memory_usage_bytes_ > max_memory_usage_bytes_) {
memory_usage_bytes_ -= resource->bytes();
return;
}
resources_.push_back(resource.release());
}
void ResourcePool::SetMaxMemoryUsageBytes(size_t max_memory_usage_bytes) {
max_memory_usage_bytes_ = max_memory_usage_bytes;
while (!resources_.empty()) {
if (memory_usage_bytes_ <= max_memory_usage_bytes_)
break;
Resource* resource = resources_.front();
resources_.pop_front();
memory_usage_bytes_ -= resource->bytes();
delete resource;
}
} }
} // namespace cc } // namespace cc
...@@ -5,14 +5,31 @@ ...@@ -5,14 +5,31 @@
#ifndef CC_RESOURCE_POOL_H_ #ifndef CC_RESOURCE_POOL_H_
#define CC_RESOURCE_POOL_H_ #define CC_RESOURCE_POOL_H_
#include <list>
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "cc/renderer.h" #include "cc/renderer.h"
#include "cc/resource_provider.h" #include "cc/resource.h"
namespace cc { namespace cc {
class ResourceProvider;
class ResourcePool { class ResourcePool {
public: public:
class Resource : public cc::Resource {
public:
Resource(ResourceProvider* resource_provider,
Renderer::ResourcePool pool_id,
const gfx::Size& size,
GLenum format);
~Resource();
private:
ResourceProvider* resource_provider_;
DISALLOW_COPY_AND_ASSIGN(Resource);
};
static scoped_ptr<ResourcePool> Create(ResourceProvider* resource_provider, static scoped_ptr<ResourcePool> Create(ResourceProvider* resource_provider,
Renderer::ResourcePool pool_id) { Renderer::ResourcePool pool_id) {
return make_scoped_ptr(new ResourcePool(resource_provider, pool_id)); return make_scoped_ptr(new ResourcePool(resource_provider, pool_id));
...@@ -22,9 +39,11 @@ class ResourcePool { ...@@ -22,9 +39,11 @@ class ResourcePool {
ResourceProvider* resource_provider() { return resource_provider_; }; ResourceProvider* resource_provider() { return resource_provider_; };
ResourceProvider::ResourceId AcquireResource( scoped_ptr<ResourcePool::Resource> AcquireResource(
const gfx::Size&, GLenum format); const gfx::Size&, GLenum format);
void ReleaseResource(ResourceProvider::ResourceId); void ReleaseResource(scoped_ptr<ResourcePool::Resource>);
void SetMaxMemoryUsageBytes(size_t max_memory_usage_bytes);
protected: protected:
ResourcePool(ResourceProvider* resource_provider, ResourcePool(ResourceProvider* resource_provider,
...@@ -33,6 +52,11 @@ class ResourcePool { ...@@ -33,6 +52,11 @@ class ResourcePool {
private: private:
ResourceProvider* resource_provider_; ResourceProvider* resource_provider_;
Renderer::ResourcePool pool_id_; Renderer::ResourcePool pool_id_;
size_t max_memory_usage_bytes_;
size_t memory_usage_bytes_;
typedef std::list<Resource*> ResourceList;
ResourceList resources_;
DISALLOW_COPY_AND_ASSIGN(ResourcePool); DISALLOW_COPY_AND_ASSIGN(ResourcePool);
}; };
......
...@@ -44,7 +44,9 @@ class CC_EXPORT Tile : public base::RefCounted<Tile> { ...@@ -44,7 +44,9 @@ class CC_EXPORT Tile : public base::RefCounted<Tile> {
void set_priority(WhichTree tree, const TilePriority& priority); void set_priority(WhichTree tree, const TilePriority& priority);
// Returns 0 if not drawable. // Returns 0 if not drawable.
ResourceProvider::ResourceId resource_id() const { return managed_state_.resource_id; } ResourceProvider::ResourceId resource_id() const {
return managed_state_.resource ? managed_state_.resource->id() : 0;
}
const gfx::Rect& opaque_rect() const { return opaque_rect_; } const gfx::Rect& opaque_rect() const { return opaque_rect_; }
......
...@@ -48,14 +48,13 @@ namespace cc { ...@@ -48,14 +48,13 @@ namespace cc {
ManagedTileState::ManagedTileState() ManagedTileState::ManagedTileState()
: can_use_gpu_memory(false), : can_use_gpu_memory(false),
can_be_freed(true), can_be_freed(true),
resource_id(0), resource_is_being_initialized(false),
resource_id_is_being_initialized(false),
contents_swizzled(false) { contents_swizzled(false) {
} }
ManagedTileState::~ManagedTileState() { ManagedTileState::~ManagedTileState() {
DCHECK(!resource_id); DCHECK(!resource);
DCHECK(!resource_id_is_being_initialized); DCHECK(!resource_is_being_initialized);
} }
TileManager::TileManager( TileManager::TileManager(
...@@ -86,6 +85,7 @@ TileManager::~TileManager() { ...@@ -86,6 +85,7 @@ TileManager::~TileManager() {
void TileManager::SetGlobalState(const GlobalStateThatImpactsTilePriority& global_state) { void TileManager::SetGlobalState(const GlobalStateThatImpactsTilePriority& global_state) {
global_state_ = global_state; global_state_ = global_state;
resource_pool_->SetMaxMemoryUsageBytes(global_state_.memory_limit_in_bytes);
ScheduleManageTiles(); ScheduleManageTiles();
} }
...@@ -263,8 +263,8 @@ void TileManager::AssignGpuMemoryToTiles() { ...@@ -263,8 +263,8 @@ void TileManager::AssignGpuMemoryToTiles() {
} }
bytes_left -= tile_bytes; bytes_left -= tile_bytes;
managed_tile_state.can_use_gpu_memory = true; managed_tile_state.can_use_gpu_memory = true;
if (!managed_tile_state.resource_id && if (!managed_tile_state.resource &&
!managed_tile_state.resource_id_is_being_initialized) !managed_tile_state.resource_is_being_initialized)
tiles_that_need_to_be_rasterized_.push_back(tile); tiles_that_need_to_be_rasterized_.push_back(tile);
} }
...@@ -278,10 +278,8 @@ void TileManager::AssignGpuMemoryToTiles() { ...@@ -278,10 +278,8 @@ void TileManager::AssignGpuMemoryToTiles() {
void TileManager::FreeResourcesForTile(Tile* tile) { void TileManager::FreeResourcesForTile(Tile* tile) {
ManagedTileState& managed_tile_state = tile->managed_state(); ManagedTileState& managed_tile_state = tile->managed_state();
DCHECK(managed_tile_state.can_be_freed); DCHECK(managed_tile_state.can_be_freed);
if (managed_tile_state.resource_id) { if (managed_tile_state.resource)
resource_pool_->ReleaseResource(managed_tile_state.resource_id); resource_pool_->ReleaseResource(managed_tile_state.resource.Pass());
managed_tile_state.resource_id = 0;
}
} }
void TileManager::DispatchMoreRasterTasks() { void TileManager::DispatchMoreRasterTasks() {
...@@ -305,13 +303,14 @@ void TileManager::DispatchOneRasterTask(scoped_refptr<Tile> tile) { ...@@ -305,13 +303,14 @@ void TileManager::DispatchOneRasterTask(scoped_refptr<Tile> tile) {
ManagedTileState& managed_tile_state = tile->managed_state(); ManagedTileState& managed_tile_state = tile->managed_state();
DCHECK(managed_tile_state.can_use_gpu_memory); DCHECK(managed_tile_state.can_use_gpu_memory);
ResourceProvider::ResourceId resource_id = scoped_ptr<ResourcePool::Resource> resource =
resource_pool_->AcquireResource(tile->tile_size_.size(), tile->format_); resource_pool_->AcquireResource(tile->tile_size_.size(), tile->format_);
resource_pool_->resource_provider()->acquirePixelBuffer(resource_id); resource_pool_->resource_provider()->acquirePixelBuffer(resource->id());
managed_tile_state.resource_id_is_being_initialized = true; managed_tile_state.resource_is_being_initialized = true;
managed_tile_state.can_be_freed = false; managed_tile_state.can_be_freed = false;
ResourceProvider::ResourceId resource_id = resource->id();
RenderingStats* stats = new RenderingStats(); RenderingStats* stats = new RenderingStats();
++pending_raster_tasks_; ++pending_raster_tasks_;
...@@ -327,14 +326,14 @@ void TileManager::DispatchOneRasterTask(scoped_refptr<Tile> tile) { ...@@ -327,14 +326,14 @@ void TileManager::DispatchOneRasterTask(scoped_refptr<Tile> tile) {
base::Bind(&TileManager::OnRasterTaskCompleted, base::Bind(&TileManager::OnRasterTaskCompleted,
base::Unretained(this), base::Unretained(this),
tile, tile,
resource_id, base::Passed(&resource),
cloned_picture_pile, cloned_picture_pile,
stats)); stats));
} }
void TileManager::OnRasterTaskCompleted( void TileManager::OnRasterTaskCompleted(
scoped_refptr<Tile> tile, scoped_refptr<Tile> tile,
ResourceProvider::ResourceId resource_id, scoped_ptr<ResourcePool::Resource> resource,
scoped_refptr<PicturePileImpl> cloned_picture_pile, scoped_refptr<PicturePileImpl> cloned_picture_pile,
RenderingStats* stats) { RenderingStats* stats) {
TRACE_EVENT0("cc", "TileManager::OnRasterTaskCompleted"); TRACE_EVENT0("cc", "TileManager::OnRasterTaskCompleted");
...@@ -346,7 +345,7 @@ void TileManager::OnRasterTaskCompleted( ...@@ -346,7 +345,7 @@ void TileManager::OnRasterTaskCompleted(
delete stats; delete stats;
// Release raster resources. // Release raster resources.
resource_pool_->resource_provider()->unmapPixelBuffer(resource_id); resource_pool_->resource_provider()->unmapPixelBuffer(resource->id());
ManagedTileState& managed_tile_state = tile->managed_state(); ManagedTileState& managed_tile_state = tile->managed_state();
managed_tile_state.can_be_freed = true; managed_tile_state.can_be_freed = true;
...@@ -361,8 +360,8 @@ void TileManager::OnRasterTaskCompleted( ...@@ -361,8 +360,8 @@ void TileManager::OnRasterTaskCompleted(
// Finish resource initialization if |can_use_gpu_memory| is true. // Finish resource initialization if |can_use_gpu_memory| is true.
if (managed_tile_state.can_use_gpu_memory) { if (managed_tile_state.can_use_gpu_memory) {
resource_pool_->resource_provider()->setPixelsFromBuffer(resource_id); resource_pool_->resource_provider()->setPixelsFromBuffer(resource->id());
resource_pool_->resource_provider()->releasePixelBuffer(resource_id); resource_pool_->resource_provider()->releasePixelBuffer(resource->id());
// The component order may be bgra if we uploaded bgra pixels to rgba // The component order may be bgra if we uploaded bgra pixels to rgba
// texture. Mark contents as swizzled if image component order is // texture. Mark contents as swizzled if image component order is
...@@ -370,22 +369,22 @@ void TileManager::OnRasterTaskCompleted( ...@@ -370,22 +369,22 @@ void TileManager::OnRasterTaskCompleted(
managed_tile_state.contents_swizzled = managed_tile_state.contents_swizzled =
!PlatformColor::sameComponentOrder(tile->format_); !PlatformColor::sameComponentOrder(tile->format_);
DidFinishTileInitialization(tile, resource_id); DidFinishTileInitialization(tile, resource.Pass());
} else { } else {
resource_pool_->resource_provider()->releasePixelBuffer(resource_id); resource_pool_->resource_provider()->releasePixelBuffer(resource->id());
resource_pool_->ReleaseResource(resource_id); resource_pool_->ReleaseResource(resource.Pass());
managed_tile_state.resource_id_is_being_initialized = false; managed_tile_state.resource_is_being_initialized = false;
} }
DispatchMoreRasterTasks(); DispatchMoreRasterTasks();
} }
void TileManager::DidFinishTileInitialization( void TileManager::DidFinishTileInitialization(
Tile* tile, ResourceProvider::ResourceId resource_id) { Tile* tile, scoped_ptr<ResourcePool::Resource> resource) {
ManagedTileState& managed_tile_state = tile->managed_state(); ManagedTileState& managed_tile_state = tile->managed_state();
DCHECK(!managed_tile_state.resource_id); DCHECK(!managed_tile_state.resource);
managed_tile_state.resource_id = resource_id; managed_tile_state.resource = resource.Pass();
managed_tile_state.resource_id_is_being_initialized = false; managed_tile_state.resource_is_being_initialized = false;
// TODO(qinmin): Make this conditional on managed_tile_state.bin == NOW_BIN. // TODO(qinmin): Make this conditional on managed_tile_state.bin == NOW_BIN.
client_->ScheduleRedraw(); client_->ScheduleRedraw();
} }
......
...@@ -52,8 +52,8 @@ class CC_EXPORT ManagedTileState { ...@@ -52,8 +52,8 @@ class CC_EXPORT ManagedTileState {
// Persisted state: valid all the time. // Persisted state: valid all the time.
bool can_use_gpu_memory; bool can_use_gpu_memory;
bool can_be_freed; bool can_be_freed;
ResourceProvider::ResourceId resource_id; scoped_ptr<ResourcePool::Resource> resource;
bool resource_id_is_being_initialized; bool resource_is_being_initialized;
bool contents_swizzled; bool contents_swizzled;
// Ephemeral state, valid only during Manage. // Ephemeral state, valid only during Manage.
...@@ -95,10 +95,10 @@ class CC_EXPORT TileManager { ...@@ -95,10 +95,10 @@ class CC_EXPORT TileManager {
void DispatchOneRasterTask(scoped_refptr<Tile>); void DispatchOneRasterTask(scoped_refptr<Tile>);
void OnRasterTaskCompleted( void OnRasterTaskCompleted(
scoped_refptr<Tile>, scoped_refptr<Tile>,
ResourceProvider::ResourceId, scoped_ptr<ResourcePool::Resource>,
scoped_refptr<PicturePileImpl>, scoped_refptr<PicturePileImpl>,
RenderingStats*); RenderingStats*);
void DidFinishTileInitialization(Tile*, ResourceProvider::ResourceId); void DidFinishTileInitialization(Tile*, scoped_ptr<ResourcePool::Resource>);
TileManagerClient* client_; TileManagerClient* client_;
scoped_ptr<ResourcePool> resource_pool_; scoped_ptr<ResourcePool> resource_pool_;
......
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