diff options
author | reveman@chromium.org <reveman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-12-05 19:06:18 +0000 |
---|---|---|
committer | reveman@chromium.org <reveman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-12-05 19:06:18 +0000 |
commit | 020909963f5684d47c99bd12a3d3cd246bfe8132 (patch) | |
tree | 19ff1275575703bb4bd2ae5d00133bcb4d336bc0 | |
parent | 212b0e3e8df63c4dcf7b13f997ef3319f6ab6947 (diff) | |
download | chromium_src-020909963f5684d47c99bd12a3d3cd246bfe8132.zip chromium_src-020909963f5684d47c99bd12a3d3cd246bfe8132.tar.gz chromium_src-020909963f5684d47c99bd12a3d3cd246bfe8132.tar.bz2 |
cc: Reduce picture cloning by creating at most one clone per raster thread.
This adds raster sequences to the TileManager. Raster tasks posted to
the same sequence are guaranteed to run in sequential order, which means
only one picture clone per sequence is required. We use the same number
of raster sequences as raster threads.
BUG=155209
TEST=manual
Review URL: https://chromiumcodereview.appspot.com/11419262
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@171267 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | cc/picture_pile.cc | 2 | ||||
-rw-r--r-- | cc/picture_pile_impl.cc | 13 | ||||
-rw-r--r-- | cc/picture_pile_impl.h | 10 | ||||
-rw-r--r-- | cc/tile.h | 2 | ||||
-rw-r--r-- | cc/tile_manager.cc | 173 | ||||
-rw-r--r-- | cc/tile_manager.h | 15 |
6 files changed, 145 insertions, 70 deletions
diff --git a/cc/picture_pile.cc b/cc/picture_pile.cc index 1e91090..eab92c6 100644 --- a/cc/picture_pile.cc +++ b/cc/picture_pile.cc @@ -98,6 +98,8 @@ void PicturePile::ResetPile(ContentLayerClient* painter, void PicturePile::PushPropertiesTo(PicturePileImpl* other) { other->pile_ = pile_; + // Remove all old clones. + other->clones_.clear(); } } // namespace cc diff --git a/cc/picture_pile_impl.cc b/cc/picture_pile_impl.cc index 530a97e..f8e56cc 100644 --- a/cc/picture_pile_impl.cc +++ b/cc/picture_pile_impl.cc @@ -20,6 +20,19 @@ PicturePileImpl::PicturePileImpl() { PicturePileImpl::~PicturePileImpl() { } +PicturePileImpl* PicturePileImpl::GetCloneForDrawingOnThread( + base::Thread* thread) { + // Do we have a clone for this thread yet? + CloneMap::iterator it = clones_.find(thread->thread_id()); + if (it != clones_.end()) + return it->second; + + // Create clone for this thread. + scoped_refptr<PicturePileImpl> clone = CloneForDrawing(); + clones_[thread->thread_id()] = clone; + return clone; +} + scoped_refptr<PicturePileImpl> PicturePileImpl::CloneForDrawing() const { TRACE_EVENT0("cc", "PicturePileImpl::CloneForDrawing"); scoped_refptr<PicturePileImpl> clone = Create(); diff --git a/cc/picture_pile_impl.h b/cc/picture_pile_impl.h index 93ac072..b041635 100644 --- a/cc/picture_pile_impl.h +++ b/cc/picture_pile_impl.h @@ -5,8 +5,11 @@ #ifndef CC_PICTURE_PILE_IMPL_H_ #define CC_PICTURE_PILE_IMPL_H_ +#include <map> + #include "base/basictypes.h" #include "base/memory/ref_counted.h" +#include "base/threading/thread.h" #include "cc/cc_export.h" #include "cc/picture.h" #include "cc/picture_pile.h" @@ -20,6 +23,9 @@ class CC_EXPORT PicturePileImpl : public base::RefCounted<PicturePileImpl> { public: static scoped_refptr<PicturePileImpl> Create(); + // Get paint-safe version of this picture for a specific thread. + PicturePileImpl* GetCloneForDrawingOnThread(base::Thread*); + // Clone a paint-safe version of this picture. scoped_refptr<PicturePileImpl> CloneForDrawing() const; @@ -40,6 +46,10 @@ private: PicturePile::Pile pile_; + typedef std::map<base::PlatformThreadId, scoped_refptr<PicturePileImpl> > + CloneMap; + CloneMap clones_; + friend class base::RefCounted<PicturePileImpl>; DISALLOW_COPY_AND_ASSIGN(PicturePileImpl); }; @@ -29,7 +29,7 @@ class CC_EXPORT Tile : public base::RefCounted<Tile> { gfx::Rect rect_inside_picture, float contents_scale); - const PicturePileImpl* picture_pile() const { + PicturePileImpl* picture_pile() { return picture_pile_.get(); } diff --git a/cc/tile_manager.cc b/cc/tile_manager.cc index a257fc3..3a1275f 100644 --- a/cc/tile_manager.cc +++ b/cc/tile_manager.cc @@ -10,7 +10,8 @@ #include "base/command_line.h" #include "base/debug/trace_event.h" #include "base/logging.h" -#include "base/threading/sequenced_worker_pool.h" +#include "base/stringprintf.h" +#include "base/threading/thread.h" #include "cc/platform_color.h" #include "cc/rendering_stats.h" #include "cc/resource_pool.h" @@ -20,27 +21,10 @@ namespace { -void RasterizeTile(cc::PicturePileImpl* picture_pile, - uint8_t* mapped_buffer, - const gfx::Rect& rect, - float contents_scale, - cc::RenderingStats* stats) { - TRACE_EVENT0("cc", "RasterizeTile"); - DCHECK(mapped_buffer); - DCHECK(picture_pile); - SkBitmap bitmap; - bitmap.setConfig(SkBitmap::kARGB_8888_Config, rect.width(), rect.height()); - bitmap.setPixels(mapped_buffer); - SkDevice device(bitmap); - SkCanvas canvas(&device); - picture_pile->Raster( - &canvas, - rect, - contents_scale, - stats); -} +const std::string kRasterThreadNamePrefix = "CompositorRaster"; -const char* kRasterThreadNamePrefix = "CompositorRaster"; +const int kMaxRasterThreads = 64; +const int kDefaultNumberOfRasterThreads = 1; // Allow two pending raster tasks per thread. This keeps resource usage // low while making sure raster threads aren't unnecessarily idle. @@ -50,6 +34,69 @@ const int kNumPendingRasterTasksPerThread = 2; namespace cc { +class RasterThread : public base::Thread { + public: + RasterThread(const std::string name) + : base::Thread(name.c_str()), + num_pending_tasks_(0) { + Start(); + } + virtual ~RasterThread() { + Stop(); + } + + int num_pending_tasks() { return num_pending_tasks_; } + + void PostRasterTaskAndReply(const tracked_objects::Location& from_here, + PicturePileImpl* picture_pile, + uint8_t* mapped_buffer, + const gfx::Rect& rect, + float contents_scale, + RenderingStats* stats, + const base::Closure& reply) { + ++num_pending_tasks_; + message_loop_proxy()->PostTaskAndReply( + from_here, + base::Bind(&RunRasterTask, + base::Unretained(picture_pile), + mapped_buffer, + rect, + contents_scale, + stats), + base::Bind(&RasterThread::RunReply, base::Unretained(this), reply)); + } + + private: + static void RunRasterTask(PicturePileImpl* picture_pile, + uint8_t* mapped_buffer, + const gfx::Rect& rect, + float contents_scale, + RenderingStats* stats) { + TRACE_EVENT0("cc", "RasterThread::RunRasterTask"); + DCHECK(picture_pile); + DCHECK(mapped_buffer); + SkBitmap bitmap; + bitmap.setConfig(SkBitmap::kARGB_8888_Config, rect.width(), rect.height()); + bitmap.setPixels(mapped_buffer); + SkDevice device(bitmap); + SkCanvas canvas(&device); + picture_pile->Raster( + &canvas, + rect, + contents_scale, + stats); + } + + void RunReply(const base::Closure& reply) { + --num_pending_tasks_; + reply.Run(); + } + + int num_pending_tasks_; + + DISALLOW_COPY_AND_ASSIGN(RasterThread); +}; + ManagedTileState::ManagedTileState() : can_use_gpu_memory(false), can_be_freed(true), @@ -69,23 +116,27 @@ TileManager::TileManager( : client_(client), resource_pool_(ResourcePool::Create(resource_provider, Renderer::ImplPool)), - manage_tiles_pending_(false), - pending_raster_tasks_(0), - num_raster_threads_(num_raster_threads), - worker_pool_(new base::SequencedWorkerPool(num_raster_threads, - kRasterThreadNamePrefix)) { + manage_tiles_pending_(false) { + // Initialize all threads. + while (raster_threads_.size() < num_raster_threads) { + int thread_number = raster_threads_.size() + 1; + scoped_ptr<RasterThread> thread = make_scoped_ptr( + new RasterThread(kRasterThreadNamePrefix + + StringPrintf("Worker%d", thread_number).c_str())); + raster_threads_.append(thread.Pass()); + } } TileManager::~TileManager() { // Reset global state and manage. This should cause // our memory usage to drop to zero. global_state_ = GlobalStateThatImpactsTilePriority(); - ManageTiles(); - DCHECK(tiles_.size() == 0); + AssignGpuMemoryToTiles(); // This should finish all pending raster tasks and release any // uninitialized resources. - worker_pool_->Shutdown(); - DCHECK(pending_raster_tasks_ == 0); + raster_threads_.clear(); + ManageTiles(); + DCHECK(tiles_.size() == 0); } void TileManager::SetGlobalState(const GlobalStateThatImpactsTilePriority& global_state) { @@ -289,23 +340,29 @@ void TileManager::FreeResourcesForTile(Tile* tile) { void TileManager::DispatchMoreRasterTasks() { while (!tiles_that_need_to_be_rasterized_.empty()) { - int max_pending_tasks = kNumPendingRasterTasksPerThread * - num_raster_threads_; + RasterThread* thread = 0; + + for (RasterThreadVector::iterator it = raster_threads_.begin(); + it != raster_threads_.end(); ++it) { + if ((*it)->num_pending_tasks() == kNumPendingRasterTasksPerThread) + continue; + // Check if this is the best thread we've found so far. + if (!thread || (*it)->num_pending_tasks() < thread->num_pending_tasks()) + thread = *it; + } - // Stop dispatching raster tasks when too many are pending. - if (pending_raster_tasks_ >= max_pending_tasks) - break; + // Stop dispatching tasks when all threads are busy. + if (!thread) + return; - DispatchOneRasterTask(tiles_that_need_to_be_rasterized_.back()); + DispatchOneRasterTask(thread, tiles_that_need_to_be_rasterized_.back()); tiles_that_need_to_be_rasterized_.pop_back(); } } -void TileManager::DispatchOneRasterTask(scoped_refptr<Tile> tile) { +void TileManager::DispatchOneRasterTask( + RasterThread* thread, scoped_refptr<Tile> tile) { TRACE_EVENT0("cc", "TileManager::DispatchOneRasterTask"); - scoped_refptr<PicturePileImpl> cloned_picture_pile = - tile->picture_pile()->CloneForDrawing(); - ManagedTileState& managed_tile_state = tile->managed_state(); DCHECK(managed_tile_state.can_use_gpu_memory); scoped_ptr<ResourcePool::Resource> resource = @@ -316,35 +373,31 @@ void TileManager::DispatchOneRasterTask(scoped_refptr<Tile> tile) { managed_tile_state.can_be_freed = false; ResourceProvider::ResourceId resource_id = resource->id(); + scoped_refptr<PicturePileImpl> picture_pile_clone = + tile->picture_pile()->GetCloneForDrawingOnThread(thread); RenderingStats* stats = new RenderingStats(); - ++pending_raster_tasks_; - worker_pool_->GetTaskRunnerWithShutdownBehavior( - base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)->PostTaskAndReply( - FROM_HERE, - base::Bind(&RasterizeTile, - base::Unretained(cloned_picture_pile.get()), - resource_pool_->resource_provider()->mapPixelBuffer( - resource_id), - tile->rect_inside_picture_, - tile->contents_scale(), - stats), - base::Bind(&TileManager::OnRasterTaskCompleted, - base::Unretained(this), - tile, - base::Passed(&resource), - cloned_picture_pile, - stats)); + thread->PostRasterTaskAndReply( + FROM_HERE, + picture_pile_clone.get(), + resource_pool_->resource_provider()->mapPixelBuffer(resource_id), + tile->rect_inside_picture_, + tile->contents_scale(), + stats, + base::Bind(&TileManager::OnRasterTaskCompleted, + base::Unretained(this), + tile, + base::Passed(&resource), + picture_pile_clone, + stats)); } void TileManager::OnRasterTaskCompleted( scoped_refptr<Tile> tile, scoped_ptr<ResourcePool::Resource> resource, - scoped_refptr<PicturePileImpl> cloned_picture_pile, + scoped_refptr<PicturePileImpl> picture_pile_clone, RenderingStats* stats) { TRACE_EVENT0("cc", "TileManager::OnRasterTaskCompleted"); - --pending_raster_tasks_; - rendering_stats_.totalRasterizeTimeInSeconds += stats->totalRasterizeTimeInSeconds; rendering_stats_.totalPixelsRasterized += stats->totalPixelsRasterized; diff --git a/cc/tile_manager.h b/cc/tile_manager.h index 4a02ded..43c9064 100644 --- a/cc/tile_manager.h +++ b/cc/tile_manager.h @@ -12,16 +12,13 @@ #include "cc/resource_pool.h" #include "cc/tile_priority.h" -namespace base { -class SequencedWorkerPool; -} - namespace cc { +class RasterThread; +class ResourceProvider; class Tile; class TileVersion; struct RenderingStats; -class ResourceProvider; class CC_EXPORT TileManagerClient { public: @@ -92,7 +89,7 @@ class CC_EXPORT TileManager { void FreeResourcesForTile(Tile*); void ScheduleManageTiles(); void DispatchMoreRasterTasks(); - void DispatchOneRasterTask(scoped_refptr<Tile>); + void DispatchOneRasterTask(RasterThread*, scoped_refptr<Tile>); void OnRasterTaskCompleted( scoped_refptr<Tile>, scoped_ptr<ResourcePool::Resource>, @@ -103,9 +100,6 @@ class CC_EXPORT TileManager { TileManagerClient* client_; scoped_ptr<ResourcePool> resource_pool_; bool manage_tiles_pending_; - int pending_raster_tasks_; - size_t num_raster_threads_; - scoped_refptr<base::SequencedWorkerPool> worker_pool_; GlobalStateThatImpactsTilePriority global_state_; @@ -113,6 +107,9 @@ class CC_EXPORT TileManager { TileVector tiles_; TileVector tiles_that_need_to_be_rasterized_; + typedef ScopedPtrVector<RasterThread> RasterThreadVector; + RasterThreadVector raster_threads_; + RenderingStats rendering_stats_; }; |