| Index: cc/tile_manager.cc
|
| diff --git a/cc/tile_manager.cc b/cc/tile_manager.cc
|
| index 932c2a836d4181fd8c6f099fceaf76c5e223bbf4..06b5090ccfcf5407a7a4bfc2ab7641dd42b4d263 100644
|
| --- a/cc/tile_manager.cc
|
| +++ b/cc/tile_manager.cc
|
| @@ -5,6 +5,7 @@
|
| #include "cc/tile_manager.h"
|
|
|
| #include <algorithm>
|
| +#include <set>
|
|
|
| #include "base/bind.h"
|
| #include "base/command_line.h"
|
| @@ -66,6 +67,16 @@ class RasterThread : public base::Thread {
|
| base::Bind(&RasterThread::RunReply, base::Unretained(this), reply));
|
| }
|
|
|
| + void PostImageDecodingTaskAndReply(const tracked_objects::Location& from_here,
|
| + skia::LazyPixelRef* pixel_ref,
|
| + const base::Closure& reply) {
|
| + ++num_pending_tasks_;
|
| + message_loop_proxy()->PostTaskAndReply(
|
| + from_here,
|
| + base::Bind(&RunImageDecodeTask, base::Unretained(pixel_ref)),
|
| + base::Bind(&RasterThread::RunReply, base::Unretained(this), reply));
|
| + }
|
| +
|
| private:
|
| static void RunRasterTask(PicturePileImpl* picture_pile,
|
| uint8_t* mapped_buffer,
|
| @@ -87,6 +98,11 @@ class RasterThread : public base::Thread {
|
| stats);
|
| }
|
|
|
| + static void RunImageDecodeTask(skia::LazyPixelRef* pixel_ref) {
|
| + TRACE_EVENT0("cc", "RasterThread::RunImageDecodeTask");
|
| + pixel_ref->Decode();
|
| + }
|
| +
|
| void RunReply(const base::Closure& reply) {
|
| --num_pending_tasks_;
|
| reply.Run();
|
| @@ -101,7 +117,8 @@ ManagedTileState::ManagedTileState()
|
| : can_use_gpu_memory(false),
|
| can_be_freed(true),
|
| resource_is_being_initialized(false),
|
| - contents_swizzled(false) {
|
| + contents_swizzled(false),
|
| + need_to_gather_pixel_refs(true) {
|
| }
|
|
|
| ManagedTileState::~ManagedTileState() {
|
| @@ -284,7 +301,7 @@ void TileManager::ManageTiles() {
|
| AssignGpuMemoryToTiles();
|
|
|
| // Finally, kick the rasterizer.
|
| - DispatchMoreRasterTasks();
|
| + DispatchMoreTasks();
|
| }
|
|
|
| void TileManager::CheckForCompletedSetPixels() {
|
| @@ -332,6 +349,15 @@ void TileManager::AssignGpuMemoryToTiles() {
|
| tiles_that_need_to_be_rasterized_.begin(),
|
| tiles_that_need_to_be_rasterized_.end());
|
|
|
| + // Record all the tiles in the image decoding list. A tile will not be
|
| + // inserted to the rasterizer queue if it is waiting for image decoding.
|
| + std::set<Tile*> image_decoding_tile_set;
|
| + for (std::list<Tile*>::iterator it = tiles_with_image_decoding_tasks_.begin();
|
| + it != tiles_with_image_decoding_tasks_.end(); ++it) {
|
| + image_decoding_tile_set.insert(*it);
|
| + }
|
| + tiles_with_image_decoding_tasks_.clear();
|
| +
|
| size_t bytes_left = global_state_.memory_limit_in_bytes - unreleasable_bytes;
|
| for (TileVector::iterator it = tiles_.begin(); it != tiles_.end(); ++it) {
|
| Tile* tile = *it;
|
| @@ -352,8 +378,12 @@ void TileManager::AssignGpuMemoryToTiles() {
|
| bytes_left -= tile_bytes;
|
| managed_tile_state.can_use_gpu_memory = true;
|
| if (!managed_tile_state.resource &&
|
| - !managed_tile_state.resource_is_being_initialized)
|
| - tiles_that_need_to_be_rasterized_.push_back(tile);
|
| + !managed_tile_state.resource_is_being_initialized) {
|
| + if (image_decoding_tile_set.end() != image_decoding_tile_set.find(tile))
|
| + tiles_with_image_decoding_tasks_.push_back(tile);
|
| + else
|
| + tiles_that_need_to_be_rasterized_.push_back(tile);
|
| + }
|
| }
|
|
|
| // Reverse two tiles_that_need_* vectors such that pop_back gets
|
| @@ -370,28 +400,125 @@ void TileManager::FreeResourcesForTile(Tile* tile) {
|
| resource_pool_->ReleaseResource(managed_tile_state.resource.Pass());
|
| }
|
|
|
| -void TileManager::DispatchMoreRasterTasks() {
|
| - while (!tiles_that_need_to_be_rasterized_.empty()) {
|
| - 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;
|
| - }
|
| +RasterThread* TileManager::GetFreeRasterThread() {
|
| + 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;
|
| + }
|
| + return thread;
|
| +}
|
|
|
| - // Stop dispatching tasks when all threads are busy.
|
| - if (!thread)
|
| +void TileManager::DispatchMoreTasks() {
|
| + // Because tiles in the image decoding list have higher priorities, we
|
| + // need to process those tiles first before we start to handle the tiles
|
| + // in the need_to_be_rasterized queue.
|
| + std::list<Tile*>::iterator it = tiles_with_image_decoding_tasks_.begin();
|
| + while (it != tiles_with_image_decoding_tasks_.end()) {
|
| + DispatchImageDecodingTasksForTile(*it);
|
| + ManagedTileState& managed_state = (*it)->managed_state();
|
| + if (managed_state.pending_pixel_refs.empty()) {
|
| + RasterThread* thread = GetFreeRasterThread();
|
| + if (!thread)
|
| return;
|
| + DispatchOneRasterTask(thread, *it);
|
| + tiles_with_image_decoding_tasks_.erase(it++);
|
| + } else {
|
| + ++it;
|
| + }
|
| + }
|
|
|
| - DispatchOneRasterTask(thread, tiles_that_need_to_be_rasterized_.back());
|
| + // Process all tiles in the need_to_be_rasterized queue. If a tile has
|
| + // image decoding tasks, put it to the back of the image decoding list.
|
| + while (!tiles_that_need_to_be_rasterized_.empty()) {
|
| + Tile* tile = tiles_that_need_to_be_rasterized_.back();
|
| + DispatchImageDecodingTasksForTile(tile);
|
| + ManagedTileState& managed_state = tile->managed_state();
|
| + if (!managed_state.pending_pixel_refs.empty()) {
|
| + tiles_with_image_decoding_tasks_.push_back(tile);
|
| + } else {
|
| + RasterThread* thread = GetFreeRasterThread();
|
| + if (!thread)
|
| + return;
|
| + DispatchOneRasterTask(thread, tile);
|
| + }
|
| tiles_that_need_to_be_rasterized_.pop_back();
|
| }
|
| }
|
|
|
| +void TileManager::DispatchImageDecodingTasksForTile(Tile* tile) {
|
| + ManagedTileState& managed_state = tile->managed_state();
|
| + if (managed_state.need_to_gather_pixel_refs) {
|
| + TRACE_EVENT0("cc",
|
| + "TileManager::DispatchImageDecodingTaskForTile: Gather PixelRefs");
|
| + const_cast<PicturePileImpl *>(tile->picture_pile())->GatherPixelRefs(
|
| + tile->content_rect_, managed_state.pending_pixel_refs);
|
| + managed_state.need_to_gather_pixel_refs = false;
|
| + }
|
| +
|
| + std::list<skia::LazyPixelRef*>& pending_pixel_refs =
|
| + tile->managed_state().pending_pixel_refs;
|
| + std::list<skia::LazyPixelRef*>::iterator it = pending_pixel_refs.begin();
|
| + while (it != pending_pixel_refs.end()) {
|
| + if (pending_decode_tasks_.end() != pending_decode_tasks_.find(
|
| + (*it)->getGenerationID())) {
|
| + ++it;
|
| + continue;
|
| + }
|
| + // TODO(qinmin): passing correct image size to PrepareToDecode().
|
| + if ((*it)->PrepareToDecode(skia::LazyPixelRef::PrepareParams())) {
|
| + pending_pixel_refs.erase(it++);
|
| + } else {
|
| + RasterThread* thread = GetFreeRasterThread();
|
| + if (thread)
|
| + DispatchOneImageDecodingTask(thread, tile, *it);
|
| + ++it;
|
| + }
|
| + }
|
| +}
|
| +
|
| +void TileManager::DispatchOneImageDecodingTask(RasterThread* thread,
|
| + scoped_refptr<Tile> tile,
|
| + skia::LazyPixelRef* pixel_ref) {
|
| + TRACE_EVENT0("cc", "TileManager::DispatchOneImageDecodingTask");
|
| + uint32_t pixel_ref_id = pixel_ref->getGenerationID();
|
| + DCHECK(pending_decode_tasks_.end() ==
|
| + pending_decode_tasks_.find(pixel_ref_id));
|
| + pending_decode_tasks_[pixel_ref_id] = pixel_ref;
|
| +
|
| + thread->PostImageDecodingTaskAndReply(
|
| + FROM_HERE,
|
| + pixel_ref,
|
| + base::Bind(&TileManager::OnImageDecodingTaskCompleted,
|
| + base::Unretained(this),
|
| + tile,
|
| + pixel_ref_id));
|
| +}
|
| +
|
| +void TileManager::OnImageDecodingTaskCompleted(scoped_refptr<Tile> tile,
|
| + uint32_t pixel_ref_id) {
|
| + TRACE_EVENT0("cc", "TileManager::OnImageDecoded");
|
| + pending_decode_tasks_.erase(pixel_ref_id);
|
| +
|
| + for (TileList::iterator it = tiles_with_image_decoding_tasks_.begin();
|
| + it != tiles_with_image_decoding_tasks_.end(); ++it) {
|
| + std::list<skia::LazyPixelRef*>& pixel_refs =
|
| + (*it)->managed_state().pending_pixel_refs;
|
| + for (std::list<skia::LazyPixelRef*>::iterator pixel_it =
|
| + pixel_refs.begin(); pixel_it != pixel_refs.end(); ++pixel_it) {
|
| + if (pixel_ref_id == (*pixel_it)->getGenerationID()) {
|
| + pixel_refs.erase(pixel_it);
|
| + break;
|
| + }
|
| + }
|
| + }
|
| + DispatchMoreTasks();
|
| +}
|
| +
|
| void TileManager::DispatchOneRasterTask(
|
| RasterThread* thread, scoped_refptr<Tile> tile) {
|
| TRACE_EVENT0("cc", "TileManager::DispatchOneRasterTask");
|
| @@ -446,7 +573,7 @@ void TileManager::OnRasterTaskCompleted(
|
| // tiles. The result of this could be that this tile is no longer
|
| // allowed to use gpu memory and in that case we need to abort
|
| // initialization and free all associated resources before calling
|
| - // DispatchMoreRasterTasks().
|
| + // DispatchMoreTasks().
|
| AssignGpuMemoryToTiles();
|
|
|
| // Finish resource initialization if |can_use_gpu_memory| is true.
|
| @@ -470,8 +597,7 @@ void TileManager::OnRasterTaskCompleted(
|
| resource_pool_->ReleaseResource(resource.Pass());
|
| managed_tile_state.resource_is_being_initialized = false;
|
| }
|
| -
|
| - DispatchMoreRasterTasks();
|
| + DispatchMoreTasks();
|
| }
|
|
|
| void TileManager::DidFinishTileInitialization(Tile* tile) {
|
|
|