diff options
-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_; }; |