Chromium Code Reviews| Index: cc/tile_manager.cc |
| diff --git a/cc/tile_manager.cc b/cc/tile_manager.cc |
| index 5eface4e7d9bfc6fa4e6fdadcd503ed2f02d368e..1b8237fc36bca99aa65d71efe55680eb5090a51e 100644 |
| --- a/cc/tile_manager.cc |
| +++ b/cc/tile_manager.cc |
| @@ -12,11 +12,13 @@ |
| #include "base/logging.h" |
| #include "base/string_number_conversions.h" |
| #include "base/threading/sequenced_worker_pool.h" |
| +#include "cc/image.h" |
| #include "cc/platform_color.h" |
| #include "cc/rendering_stats.h" |
| #include "cc/resource_pool.h" |
| #include "cc/switches.h" |
| #include "cc/tile.h" |
| +#include "skia/ext/lazy_pixel_ref.h" |
| #include "third_party/skia/include/core/SkDevice.h" |
| namespace { |
| @@ -160,6 +162,8 @@ void TileManager::ManageTiles() { |
| const bool smoothness_takes_priority = global_state_.smoothness_takes_priority; |
| + decoding_progress_.clear(); |
|
reveman
2012/12/05 19:48:46
ManageTiles() might be called while images are bei
qinmin
2012/12/07 05:06:28
Since this variable is changed to keep track of al
|
| + |
| // Bin into three categories of tiles: things we need now, things we need soon, and eventually |
| for (TileVector::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { |
| Tile* tile = *it; |
| @@ -196,6 +200,15 @@ void TileManager::ManageTiles() { |
| } |
| mts.bin = EVENTUALLY_BIN; |
| + |
| + // Update all the SkPixelRefs this tile intersects. |
| + mts.pixel_refs.clear(); |
| + mts.pixel_refs = |
| + const_cast<PicturePileImpl *>(tile->picture_pile())->GatherPixelRefs( |
| + tile->rect_inside_picture_); |
| + for (std::vector<SkPixelRef*>::iterator it = mts.pixel_refs.begin(); |
| + it != mts.pixel_refs.end(); ++it) |
| + decoding_progress_[*it] = NOT_STARTED; |
|
reveman
2012/12/05 19:48:46
The pixel refs for a tile should never change, rig
qinmin
2012/12/07 05:06:28
Changed this to only get the skpixelref informatio
|
| } |
| // Memory limit policy works by mapping some bin states to the NEVER bin. |
| @@ -300,17 +313,91 @@ void TileManager::FreeResourcesForTile(Tile* tile) { |
| } |
| void TileManager::DispatchMoreRasterTasks() { |
| - while (!tiles_that_need_to_be_rasterized_.empty()) { |
| - int max_pending_tasks = kNumPendingRasterTasksPerThread * |
| - kMaxRasterThreads; |
| - |
| + int max_pending_tasks = kNumPendingRasterTasksPerThread * |
| + kMaxRasterThreads; |
| + bool all_tiles_waiting_for_decoder = false; |
| + while (!tiles_that_need_to_be_rasterized_.empty() && |
| + !all_tiles_waiting_for_decoder) { |
| // Stop dispatching raster tasks when too many are pending. |
| if (pending_raster_tasks_ >= max_pending_tasks) |
| break; |
| + all_tiles_waiting_for_decoder = true; |
| + // TODO(qinmin): Use a separate queue for tiles that are doing image |
| + // decoding. However, we need to find a good way to keep track of |
| + // the tile priority. Otherwise, one queue may starve the other queue. |
| + TileVector::reverse_iterator it; |
| + for (it = tiles_that_need_to_be_rasterized_.rbegin(); |
| + it != tiles_that_need_to_be_rasterized_.rend(); ++it) { |
| + std::vector<SkPixelRef*> pixel_refs; |
| + if (HasUndecodedImages(*it, pixel_refs)) { |
| + if (pixel_refs.empty()) |
| + continue; |
| + for (std::vector<SkPixelRef*>::iterator it = pixel_refs.begin(); |
| + it != pixel_refs.end(); ++it) { |
| + SpawnImageDecodingTask(*it); |
| + // If we are reaching the task limit, just finish here and wait for |
| + // tasks to finish. |
| + if (pending_raster_tasks_ >= max_pending_tasks) |
| + return; |
| + } |
| + } else { |
| + DispatchOneRasterTask(*it); |
| + all_tiles_waiting_for_decoder = false; |
| + // Be cautious that we are erasing a reverse iterator. |
| + tiles_that_need_to_be_rasterized_.erase(--it.base()); |
| + break; |
| + } |
| + } |
|
reveman
2012/12/05 19:48:46
I think we're starting to do too much in this func
qinmin
2012/12/07 05:06:28
Done. Now all the jobs waiting on image decoding g
|
| + } |
| +} |
| - DispatchOneRasterTask(tiles_that_need_to_be_rasterized_.back()); |
| - tiles_that_need_to_be_rasterized_.pop_back(); |
| +bool TileManager::HasUndecodedImages(Tile* tile, |
|
reveman
2012/12/05 19:48:46
Could we just remove SkPixelRefs from managed_stat
reveman
2012/12/05 20:28:35
I guess we still need a map with all the pixel ref
qinmin
2012/12/07 05:06:28
we cannot remove SkPixelRef if the decoding task j
|
| + std::vector<SkPixelRef*>& unstarted) { |
| + bool has_undecoded_images = false; |
| + SkPixelRef* decode_not_started = 0; |
| + ManagedTileState& managed_state = tile->managed_state(); |
| + for (std::vector<SkPixelRef*>::iterator it = managed_state.pixel_refs.begin(); |
| + it != managed_state.pixel_refs.end(); ++it) { |
| + bool not_started = false; |
| + switch(decoding_progress_[*it]) { |
| + case FINISHED: |
| + break; |
| + case NOT_STARTED: |
| + not_started = true; |
| + case IN_PROGRESS: |
| + scoped_refptr<Image> image(Image::Create(*it)); |
| + // If image is already in cache, don't spawn decode task. |
| + if (!image->PrepareToDecode()) { |
| + has_undecoded_images = true; |
| + if (not_started) |
| + unstarted.push_back(*it); |
| + } |
| + } |
| } |
| + return has_undecoded_images; |
| +} |
| + |
| +void TileManager::SpawnImageDecodingTask(SkPixelRef* pixel_ref) { |
| + TRACE_EVENT0("cc", "TileManager::SpawnImageDecodingTask"); |
| + scoped_refptr<Image> image(Image::Create(pixel_ref)); |
|
reveman
2012/12/05 19:48:46
Doesn't look like image need to be ref counted. Ca
reveman
2012/12/05 20:28:35
Would it make sense to add a ScopedPtrHashMap<SkPi
qinmin
2012/12/07 05:06:28
Removed the image class. However, I am not sure wh
|
| + // Kicking off a image decode job. |
| + ++pending_raster_tasks_; |
| + worker_pool_->GetTaskRunnerWithShutdownBehavior( |
| + base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)->PostTaskAndReply( |
| + FROM_HERE, |
| + base::Bind(&Image::Decode, |
|
Alpha Left Google
2012/12/05 20:24:28
This is fine now but just be aware that after this
qinmin
2012/12/07 05:06:28
Yes, redecoding can be problematic if the cache go
|
| + image), |
| + base::Bind(&TileManager::OnImageDecoded, |
| + base::Unretained(this), |
|
reveman
2012/12/05 19:48:46
Each decoding task is associated with a tile and d
qinmin
2012/12/07 05:06:28
I think when we kick off the image decoder, we alw
|
| + image)); |
| + decoding_progress_[pixel_ref] = IN_PROGRESS; |
| +} |
| + |
| +void TileManager::OnImageDecoded(scoped_refptr<Image> image) { |
| + TRACE_EVENT0("cc", "TileManager::OnImageDecoded"); |
| + --pending_raster_tasks_; |
| + decoding_progress_[image->pixel_ref()] = FINISHED; |
| + DispatchMoreRasterTasks(); |
| } |
| void TileManager::DispatchOneRasterTask(scoped_refptr<Tile> tile) { |