summaryrefslogtreecommitdiffstats
path: root/cc
diff options
context:
space:
mode:
Diffstat (limited to 'cc')
-rw-r--r--cc/picture_pile.cc2
-rw-r--r--cc/picture_pile_impl.cc13
-rw-r--r--cc/picture_pile_impl.h10
-rw-r--r--cc/tile.h2
-rw-r--r--cc/tile_manager.cc174
-rw-r--r--cc/tile_manager.h15
6 files changed, 146 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);
};
diff --git a/cc/tile.h b/cc/tile.h
index a88d6ea..f3702f7 100644
--- a/cc/tile.h
+++ b/cc/tile.h
@@ -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..80c2c74 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,28 +21,11 @@
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 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.
const int kNumPendingRasterTasksPerThread = 2;
@@ -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,28 @@ 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.
+ const std::string thread_name_prefix = kRasterThreadNamePrefix;
+ while (raster_threads_.size() < num_raster_threads) {
+ int thread_number = raster_threads_.size() + 1;
+ scoped_ptr<RasterThread> thread = make_scoped_ptr(
+ new RasterThread(thread_name_prefix +
+ 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 +341,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 +374,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_;
};