OLD | NEW |
---|---|
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "cc/tile_manager.h" | 5 #include "cc/tile_manager.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
11 #include "base/debug/trace_event.h" | 11 #include "base/debug/trace_event.h" |
12 #include "base/logging.h" | 12 #include "base/logging.h" |
13 #include "base/string_number_conversions.h" | 13 #include "base/string_number_conversions.h" |
14 #include "base/threading/sequenced_worker_pool.h" | 14 #include "base/threading/sequenced_worker_pool.h" |
15 #include "cc/image.h" | |
15 #include "cc/platform_color.h" | 16 #include "cc/platform_color.h" |
16 #include "cc/rendering_stats.h" | 17 #include "cc/rendering_stats.h" |
17 #include "cc/resource_pool.h" | 18 #include "cc/resource_pool.h" |
18 #include "cc/switches.h" | 19 #include "cc/switches.h" |
19 #include "cc/tile.h" | 20 #include "cc/tile.h" |
21 #include "skia/ext/lazy_pixel_ref.h" | |
20 #include "third_party/skia/include/core/SkDevice.h" | 22 #include "third_party/skia/include/core/SkDevice.h" |
21 | 23 |
22 namespace { | 24 namespace { |
23 | 25 |
24 void RasterizeTile(cc::PicturePileImpl* picture_pile, | 26 void RasterizeTile(cc::PicturePileImpl* picture_pile, |
25 uint8_t* mapped_buffer, | 27 uint8_t* mapped_buffer, |
26 const gfx::Rect& rect, | 28 const gfx::Rect& rect, |
27 cc::RenderingStats* stats) { | 29 cc::RenderingStats* stats) { |
28 TRACE_EVENT0("cc", "RasterizeTile"); | 30 TRACE_EVENT0("cc", "RasterizeTile"); |
29 DCHECK(mapped_buffer); | 31 DCHECK(mapped_buffer); |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
153 void TileManager::ManageTiles() { | 155 void TileManager::ManageTiles() { |
154 TRACE_EVENT0("cc", "TileManager::ManageTiles"); | 156 TRACE_EVENT0("cc", "TileManager::ManageTiles"); |
155 manage_tiles_pending_ = false; | 157 manage_tiles_pending_ = false; |
156 | 158 |
157 // The amount of time for which we want to have prepainting coverage. | 159 // The amount of time for which we want to have prepainting coverage. |
158 const double prepainting_window_time_seconds = 1.0; | 160 const double prepainting_window_time_seconds = 1.0; |
159 const double backfling_guard_distance_pixels = 314.0; | 161 const double backfling_guard_distance_pixels = 314.0; |
160 | 162 |
161 const bool smoothness_takes_priority = global_state_.smoothness_takes_priority ; | 163 const bool smoothness_takes_priority = global_state_.smoothness_takes_priority ; |
162 | 164 |
165 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
| |
166 | |
163 // Bin into three categories of tiles: things we need now, things we need soon , and eventually | 167 // Bin into three categories of tiles: things we need now, things we need soon , and eventually |
164 for (TileVector::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { | 168 for (TileVector::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { |
165 Tile* tile = *it; | 169 Tile* tile = *it; |
166 ManagedTileState& mts = tile->managed_state(); | 170 ManagedTileState& mts = tile->managed_state(); |
167 TilePriority prio; | 171 TilePriority prio; |
168 if (smoothness_takes_priority) | 172 if (smoothness_takes_priority) |
169 prio = tile->priority(ACTIVE_TREE); | 173 prio = tile->priority(ACTIVE_TREE); |
170 else | 174 else |
171 prio = tile->combined_priority(); | 175 prio = tile->combined_priority(); |
172 | 176 |
(...skipping 16 matching lines...) Expand all Loading... | |
189 mts.bin = NOW_BIN; | 193 mts.bin = NOW_BIN; |
190 continue; | 194 continue; |
191 } | 195 } |
192 | 196 |
193 if (prio.time_to_needed_in_seconds() < prepainting_window_time_seconds) { | 197 if (prio.time_to_needed_in_seconds() < prepainting_window_time_seconds) { |
194 mts.bin = SOON_BIN; | 198 mts.bin = SOON_BIN; |
195 continue; | 199 continue; |
196 } | 200 } |
197 | 201 |
198 mts.bin = EVENTUALLY_BIN; | 202 mts.bin = EVENTUALLY_BIN; |
203 | |
204 // Update all the SkPixelRefs this tile intersects. | |
205 mts.pixel_refs.clear(); | |
206 mts.pixel_refs = | |
207 const_cast<PicturePileImpl *>(tile->picture_pile())->GatherPixelRefs( | |
208 tile->rect_inside_picture_); | |
209 for (std::vector<SkPixelRef*>::iterator it = mts.pixel_refs.begin(); | |
210 it != mts.pixel_refs.end(); ++it) | |
211 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
| |
199 } | 212 } |
200 | 213 |
201 // Memory limit policy works by mapping some bin states to the NEVER bin. | 214 // Memory limit policy works by mapping some bin states to the NEVER bin. |
202 TileManagerBin bin_map[NUM_BINS]; | 215 TileManagerBin bin_map[NUM_BINS]; |
203 if (global_state_.memory_limit_policy == ALLOW_NOTHING) { | 216 if (global_state_.memory_limit_policy == ALLOW_NOTHING) { |
204 bin_map[NOW_BIN] = NEVER_BIN; | 217 bin_map[NOW_BIN] = NEVER_BIN; |
205 bin_map[SOON_BIN] = NEVER_BIN; | 218 bin_map[SOON_BIN] = NEVER_BIN; |
206 bin_map[EVENTUALLY_BIN] = NEVER_BIN; | 219 bin_map[EVENTUALLY_BIN] = NEVER_BIN; |
207 bin_map[NEVER_BIN] = NEVER_BIN; | 220 bin_map[NEVER_BIN] = NEVER_BIN; |
208 } else if (global_state_.memory_limit_policy == ALLOW_ABSOLUTE_MINIMUM) { | 221 } else if (global_state_.memory_limit_policy == ALLOW_ABSOLUTE_MINIMUM) { |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
293 void TileManager::FreeResourcesForTile(Tile* tile) { | 306 void TileManager::FreeResourcesForTile(Tile* tile) { |
294 ManagedTileState& managed_tile_state = tile->managed_state(); | 307 ManagedTileState& managed_tile_state = tile->managed_state(); |
295 DCHECK(managed_tile_state.can_be_freed); | 308 DCHECK(managed_tile_state.can_be_freed); |
296 if (managed_tile_state.resource_id) { | 309 if (managed_tile_state.resource_id) { |
297 resource_pool_->ReleaseResource(managed_tile_state.resource_id); | 310 resource_pool_->ReleaseResource(managed_tile_state.resource_id); |
298 managed_tile_state.resource_id = 0; | 311 managed_tile_state.resource_id = 0; |
299 } | 312 } |
300 } | 313 } |
301 | 314 |
302 void TileManager::DispatchMoreRasterTasks() { | 315 void TileManager::DispatchMoreRasterTasks() { |
303 while (!tiles_that_need_to_be_rasterized_.empty()) { | 316 int max_pending_tasks = kNumPendingRasterTasksPerThread * |
304 int max_pending_tasks = kNumPendingRasterTasksPerThread * | 317 kMaxRasterThreads; |
305 kMaxRasterThreads; | 318 bool all_tiles_waiting_for_decoder = false; |
306 | 319 while (!tiles_that_need_to_be_rasterized_.empty() && |
320 !all_tiles_waiting_for_decoder) { | |
307 // Stop dispatching raster tasks when too many are pending. | 321 // Stop dispatching raster tasks when too many are pending. |
308 if (pending_raster_tasks_ >= max_pending_tasks) | 322 if (pending_raster_tasks_ >= max_pending_tasks) |
309 break; | 323 break; |
310 | 324 all_tiles_waiting_for_decoder = true; |
311 DispatchOneRasterTask(tiles_that_need_to_be_rasterized_.back()); | 325 // TODO(qinmin): Use a separate queue for tiles that are doing image |
312 tiles_that_need_to_be_rasterized_.pop_back(); | 326 // decoding. However, we need to find a good way to keep track of |
327 // the tile priority. Otherwise, one queue may starve the other queue. | |
328 TileVector::reverse_iterator it; | |
329 for (it = tiles_that_need_to_be_rasterized_.rbegin(); | |
330 it != tiles_that_need_to_be_rasterized_.rend(); ++it) { | |
331 std::vector<SkPixelRef*> pixel_refs; | |
332 if (HasUndecodedImages(*it, pixel_refs)) { | |
333 if (pixel_refs.empty()) | |
334 continue; | |
335 for (std::vector<SkPixelRef*>::iterator it = pixel_refs.begin(); | |
336 it != pixel_refs.end(); ++it) { | |
337 SpawnImageDecodingTask(*it); | |
338 // If we are reaching the task limit, just finish here and wait for | |
339 // tasks to finish. | |
340 if (pending_raster_tasks_ >= max_pending_tasks) | |
341 return; | |
342 } | |
343 } else { | |
344 DispatchOneRasterTask(*it); | |
345 all_tiles_waiting_for_decoder = false; | |
346 // Be cautious that we are erasing a reverse iterator. | |
347 tiles_that_need_to_be_rasterized_.erase(--it.base()); | |
348 break; | |
349 } | |
350 } | |
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
| |
313 } | 351 } |
314 } | 352 } |
315 | 353 |
354 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
| |
355 std::vector<SkPixelRef*>& unstarted) { | |
356 bool has_undecoded_images = false; | |
357 SkPixelRef* decode_not_started = 0; | |
358 ManagedTileState& managed_state = tile->managed_state(); | |
359 for (std::vector<SkPixelRef*>::iterator it = managed_state.pixel_refs.begin(); | |
360 it != managed_state.pixel_refs.end(); ++it) { | |
361 bool not_started = false; | |
362 switch(decoding_progress_[*it]) { | |
363 case FINISHED: | |
364 break; | |
365 case NOT_STARTED: | |
366 not_started = true; | |
367 case IN_PROGRESS: | |
368 scoped_refptr<Image> image(Image::Create(*it)); | |
369 // If image is already in cache, don't spawn decode task. | |
370 if (!image->PrepareToDecode()) { | |
371 has_undecoded_images = true; | |
372 if (not_started) | |
373 unstarted.push_back(*it); | |
374 } | |
375 } | |
376 } | |
377 return has_undecoded_images; | |
378 } | |
379 | |
380 void TileManager::SpawnImageDecodingTask(SkPixelRef* pixel_ref) { | |
381 TRACE_EVENT0("cc", "TileManager::SpawnImageDecodingTask"); | |
382 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
| |
383 // Kicking off a image decode job. | |
384 ++pending_raster_tasks_; | |
385 worker_pool_->GetTaskRunnerWithShutdownBehavior( | |
386 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)->PostTaskAndReply( | |
387 FROM_HERE, | |
388 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
| |
389 image), | |
390 base::Bind(&TileManager::OnImageDecoded, | |
391 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
| |
392 image)); | |
393 decoding_progress_[pixel_ref] = IN_PROGRESS; | |
394 } | |
395 | |
396 void TileManager::OnImageDecoded(scoped_refptr<Image> image) { | |
397 TRACE_EVENT0("cc", "TileManager::OnImageDecoded"); | |
398 --pending_raster_tasks_; | |
399 decoding_progress_[image->pixel_ref()] = FINISHED; | |
400 DispatchMoreRasterTasks(); | |
401 } | |
402 | |
316 void TileManager::DispatchOneRasterTask(scoped_refptr<Tile> tile) { | 403 void TileManager::DispatchOneRasterTask(scoped_refptr<Tile> tile) { |
317 TRACE_EVENT0("cc", "TileManager::DispatchOneRasterTask"); | 404 TRACE_EVENT0("cc", "TileManager::DispatchOneRasterTask"); |
318 scoped_refptr<PicturePileImpl> cloned_picture_pile = | 405 scoped_refptr<PicturePileImpl> cloned_picture_pile = |
319 tile->picture_pile()->CloneForDrawing(); | 406 tile->picture_pile()->CloneForDrawing(); |
320 | 407 |
321 ManagedTileState& managed_tile_state = tile->managed_state(); | 408 ManagedTileState& managed_tile_state = tile->managed_state(); |
322 DCHECK(managed_tile_state.can_use_gpu_memory); | 409 DCHECK(managed_tile_state.can_use_gpu_memory); |
323 ResourceProvider::ResourceId resource_id = | 410 ResourceProvider::ResourceId resource_id = |
324 resource_pool_->AcquireResource(tile->tile_size_.size(), tile->format_); | 411 resource_pool_->AcquireResource(tile->tile_size_.size(), tile->format_); |
325 resource_pool_->resource_provider()->acquirePixelBuffer(resource_id); | 412 resource_pool_->resource_provider()->acquirePixelBuffer(resource_id); |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
399 Tile* tile, ResourceProvider::ResourceId resource_id) { | 486 Tile* tile, ResourceProvider::ResourceId resource_id) { |
400 ManagedTileState& managed_tile_state = tile->managed_state(); | 487 ManagedTileState& managed_tile_state = tile->managed_state(); |
401 DCHECK(!managed_tile_state.resource_id); | 488 DCHECK(!managed_tile_state.resource_id); |
402 managed_tile_state.resource_id = resource_id; | 489 managed_tile_state.resource_id = resource_id; |
403 managed_tile_state.resource_id_is_being_initialized = false; | 490 managed_tile_state.resource_id_is_being_initialized = false; |
404 // TODO(qinmin): Make this conditional on managed_tile_state.bin == NOW_BIN. | 491 // TODO(qinmin): Make this conditional on managed_tile_state.bin == NOW_BIN. |
405 client_->ScheduleRedraw(); | 492 client_->ScheduleRedraw(); |
406 } | 493 } |
407 | 494 |
408 } | 495 } |
OLD | NEW |