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/stringprintf.h" | 13 #include "base/stringprintf.h" |
14 #include "base/threading/thread.h" | 14 #include "base/threading/thread.h" |
15 #include "cc/platform_color.h" | 15 #include "cc/platform_color.h" |
16 #include "cc/rendering_stats.h" | 16 #include "cc/rendering_stats.h" |
17 #include "cc/resource_pool.h" | 17 #include "cc/resource_pool.h" |
18 #include "cc/switches.h" | 18 #include "cc/switches.h" |
19 #include "cc/tile.h" | 19 #include "cc/tile.h" |
20 #include "skia/ext/lazy_pixel_ref.h" | |
20 #include "third_party/skia/include/core/SkDevice.h" | 21 #include "third_party/skia/include/core/SkDevice.h" |
21 | 22 |
22 namespace { | 23 namespace { |
23 | 24 |
24 const char* kRasterThreadNamePrefix = "CompositorRaster"; | 25 const char* kRasterThreadNamePrefix = "CompositorRaster"; |
25 | 26 |
26 const int kMaxRasterThreads = 64; | 27 const int kMaxRasterThreads = 64; |
27 const int kDefaultNumberOfRasterThreads = 1; | 28 const int kDefaultNumberOfRasterThreads = 1; |
28 | 29 |
29 // Allow two pending raster tasks per thread. This keeps resource usage | 30 // Allow two pending raster tasks per thread. This keeps resource usage |
(...skipping 29 matching lines...) Expand all Loading... | |
59 from_here, | 60 from_here, |
60 base::Bind(&RunRasterTask, | 61 base::Bind(&RunRasterTask, |
61 base::Unretained(picture_pile), | 62 base::Unretained(picture_pile), |
62 mapped_buffer, | 63 mapped_buffer, |
63 rect, | 64 rect, |
64 contents_scale, | 65 contents_scale, |
65 stats), | 66 stats), |
66 base::Bind(&RasterThread::RunReply, base::Unretained(this), reply)); | 67 base::Bind(&RasterThread::RunReply, base::Unretained(this), reply)); |
67 } | 68 } |
68 | 69 |
70 void PostImageDecodingTaskAndReply(const tracked_objects::Location& from_here, | |
71 SkPixelRef* pixel_ref, | |
72 const base::Closure& reply) { | |
73 ++num_pending_tasks_; | |
74 message_loop_proxy()->PostTaskAndReply( | |
75 from_here, | |
76 base::Bind(&skia::LazyPixelRef::Decode, base::Unretained( | |
77 static_cast<skia::LazyPixelRef*>(pixel_ref))), | |
78 base::Bind(&RasterThread::RunReply, base::Unretained(this), reply)); | |
79 } | |
80 | |
69 private: | 81 private: |
70 static void RunRasterTask(PicturePileImpl* picture_pile, | 82 static void RunRasterTask(PicturePileImpl* picture_pile, |
71 uint8_t* mapped_buffer, | 83 uint8_t* mapped_buffer, |
72 const gfx::Rect& rect, | 84 const gfx::Rect& rect, |
73 float contents_scale, | 85 float contents_scale, |
74 RenderingStats* stats) { | 86 RenderingStats* stats) { |
75 TRACE_EVENT0("cc", "RasterThread::RunRasterTask"); | 87 TRACE_EVENT0("cc", "RasterThread::RunRasterTask"); |
76 DCHECK(picture_pile); | 88 DCHECK(picture_pile); |
77 DCHECK(mapped_buffer); | 89 DCHECK(mapped_buffer); |
78 SkBitmap bitmap; | 90 SkBitmap bitmap; |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
231 mts.bin = NOW_BIN; | 243 mts.bin = NOW_BIN; |
232 continue; | 244 continue; |
233 } | 245 } |
234 | 246 |
235 if (prio.time_to_needed_in_seconds() < prepainting_window_time_seconds) { | 247 if (prio.time_to_needed_in_seconds() < prepainting_window_time_seconds) { |
236 mts.bin = SOON_BIN; | 248 mts.bin = SOON_BIN; |
237 continue; | 249 continue; |
238 } | 250 } |
239 | 251 |
240 mts.bin = EVENTUALLY_BIN; | 252 mts.bin = EVENTUALLY_BIN; |
253 | |
254 // Update all the SkPixelRefs this tile intersects. | |
255 mts.pending_pixel_refs.clear(); | |
256 mts.has_image_decoding_info = false; | |
241 } | 257 } |
242 | 258 |
243 // Memory limit policy works by mapping some bin states to the NEVER bin. | 259 // Memory limit policy works by mapping some bin states to the NEVER bin. |
244 TileManagerBin bin_map[NUM_BINS]; | 260 TileManagerBin bin_map[NUM_BINS]; |
245 if (global_state_.memory_limit_policy == ALLOW_NOTHING) { | 261 if (global_state_.memory_limit_policy == ALLOW_NOTHING) { |
246 bin_map[NOW_BIN] = NEVER_BIN; | 262 bin_map[NOW_BIN] = NEVER_BIN; |
247 bin_map[SOON_BIN] = NEVER_BIN; | 263 bin_map[SOON_BIN] = NEVER_BIN; |
248 bin_map[EVENTUALLY_BIN] = NEVER_BIN; | 264 bin_map[EVENTUALLY_BIN] = NEVER_BIN; |
249 bin_map[NEVER_BIN] = NEVER_BIN; | 265 bin_map[NEVER_BIN] = NEVER_BIN; |
250 } else if (global_state_.memory_limit_policy == ALLOW_ABSOLUTE_MINIMUM) { | 266 } else if (global_state_.memory_limit_policy == ALLOW_ABSOLUTE_MINIMUM) { |
(...skipping 17 matching lines...) Expand all Loading... | |
268 TileManagerBin bin = bin_map[tile->managed_state().bin]; | 284 TileManagerBin bin = bin_map[tile->managed_state().bin]; |
269 tile->managed_state().bin = bin; | 285 tile->managed_state().bin = bin; |
270 } | 286 } |
271 | 287 |
272 // Sort by bin. | 288 // Sort by bin. |
273 std::sort(tiles_.begin(), tiles_.end(), BinComparator()); | 289 std::sort(tiles_.begin(), tiles_.end(), BinComparator()); |
274 | 290 |
275 // Assign gpu memory and determine what tiles need to be rasterized. | 291 // Assign gpu memory and determine what tiles need to be rasterized. |
276 AssignGpuMemoryToTiles(); | 292 AssignGpuMemoryToTiles(); |
277 | 293 |
294 // Initialize image information for tiles in the NOW_BIN. For other tiles, | |
295 // we will get the information later when decoding is about to start. | |
296 for (TileVector::reverse_iterator it = | |
297 tiles_that_need_to_be_rasterized_.rbegin(); | |
298 it != tiles_that_need_to_be_rasterized_.rend(); ++it) { | |
299 if ((*it)->managed_state().bin == NOW_BIN) | |
300 GetImageInformationForTile(*it); | |
301 else | |
302 break; | |
303 } | |
304 | |
278 // Finally, kick the rasterizer. | 305 // Finally, kick the rasterizer. |
279 DispatchMoreRasterTasks(); | 306 DispatchMoreRasterTasks(); |
280 } | 307 } |
281 | 308 |
282 void TileManager::renderingStats(RenderingStats* stats) { | 309 void TileManager::renderingStats(RenderingStats* stats) { |
283 stats->totalRasterizeTimeInSeconds = | 310 stats->totalRasterizeTimeInSeconds = |
284 rendering_stats_.totalRasterizeTimeInSeconds; | 311 rendering_stats_.totalRasterizeTimeInSeconds; |
285 stats->totalPixelsRasterized = rendering_stats_.totalPixelsRasterized; | 312 stats->totalPixelsRasterized = rendering_stats_.totalPixelsRasterized; |
286 } | 313 } |
287 | 314 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
325 tiles_that_need_to_be_rasterized_.push_back(tile); | 352 tiles_that_need_to_be_rasterized_.push_back(tile); |
326 } | 353 } |
327 | 354 |
328 // Reverse two tiles_that_need_* vectors such that pop_back gets | 355 // Reverse two tiles_that_need_* vectors such that pop_back gets |
329 // the highest priority tile. | 356 // the highest priority tile. |
330 std::reverse( | 357 std::reverse( |
331 tiles_that_need_to_be_rasterized_.begin(), | 358 tiles_that_need_to_be_rasterized_.begin(), |
332 tiles_that_need_to_be_rasterized_.end()); | 359 tiles_that_need_to_be_rasterized_.end()); |
333 } | 360 } |
334 | 361 |
362 void TileManager::GetImageInformationForTile(Tile* tile) { | |
363 ManagedTileState& managed_state = tile->managed_state(); | |
364 if (!managed_state.has_image_decoding_info) { | |
365 const_cast<PicturePileImpl *>(tile->picture_pile())->GatherPixelRefs( | |
366 tile->rect_inside_picture_, managed_state.pending_pixel_refs); | |
367 managed_state.has_image_decoding_info = true; | |
368 } | |
369 } | |
370 | |
335 void TileManager::FreeResourcesForTile(Tile* tile) { | 371 void TileManager::FreeResourcesForTile(Tile* tile) { |
336 ManagedTileState& managed_tile_state = tile->managed_state(); | 372 ManagedTileState& managed_tile_state = tile->managed_state(); |
337 DCHECK(managed_tile_state.can_be_freed); | 373 DCHECK(managed_tile_state.can_be_freed); |
338 if (managed_tile_state.resource) | 374 if (managed_tile_state.resource) |
339 resource_pool_->ReleaseResource(managed_tile_state.resource.Pass()); | 375 resource_pool_->ReleaseResource(managed_tile_state.resource.Pass()); |
340 } | 376 } |
341 | 377 |
378 RasterThread* TileManager::GetFreeRasterThread() { | |
379 RasterThread* thread = 0; | |
380 for (RasterThreadVector::iterator it = raster_threads_.begin(); | |
381 it != raster_threads_.end(); ++it) { | |
382 if ((*it)->num_pending_tasks() == kNumPendingRasterTasksPerThread) | |
383 continue; | |
384 // Check if this is the best thread we've found so far. | |
385 if (!thread || (*it)->num_pending_tasks() < thread->num_pending_tasks()) | |
386 thread = *it; | |
387 } | |
388 return thread; | |
389 } | |
390 | |
342 void TileManager::DispatchMoreRasterTasks() { | 391 void TileManager::DispatchMoreRasterTasks() { |
343 while (!tiles_that_need_to_be_rasterized_.empty()) { | 392 while (!tiles_that_need_to_be_rasterized_.empty()) { |
344 RasterThread* thread = 0; | 393 RasterThread* thread = GetFreeRasterThread(); |
345 | |
346 for (RasterThreadVector::iterator it = raster_threads_.begin(); | |
347 it != raster_threads_.end(); ++it) { | |
348 if ((*it)->num_pending_tasks() == kNumPendingRasterTasksPerThread) | |
349 continue; | |
350 // Check if this is the best thread we've found so far. | |
351 if (!thread || (*it)->num_pending_tasks() < thread->num_pending_tasks()) | |
352 thread = *it; | |
353 } | |
354 | |
355 // Stop dispatching tasks when all threads are busy. | 394 // Stop dispatching tasks when all threads are busy. |
356 if (!thread) | 395 if (!thread) |
357 return; | 396 return; |
358 | 397 |
359 DispatchOneRasterTask(thread, tiles_that_need_to_be_rasterized_.back()); | 398 Tile* tile = tiles_that_need_to_be_rasterized_.back(); |
399 if (!HasDispatchedImageDecodingTasks(tile)) | |
400 DispatchOneRasterTask(thread, tile); | |
360 tiles_that_need_to_be_rasterized_.pop_back(); | 401 tiles_that_need_to_be_rasterized_.pop_back(); |
361 } | 402 } |
362 } | 403 } |
363 | 404 |
405 bool TileManager::HasDispatchedImageDecodingTasks(Tile* tile) { | |
406 bool has_dispatched_task = false; | |
407 if (!tile->managed_state().has_image_decoding_info) | |
408 GetImageInformationForTile(tile); | |
409 | |
410 std::vector<int> index_to_be_removed; | |
411 RasterThread* thread = 0; | |
412 std::vector<SkPixelRef*>& pending_pixel_refs = | |
413 tile->managed_state().pending_pixel_refs; | |
414 for (int i = 0; i < pending_pixel_refs.size(); ++i) { | |
415 SkPixelRef* pixel_ref = pending_pixel_refs[i]; | |
416 if (pending_decode_tasks_.end() != pending_decode_tasks_.find( | |
417 pixel_ref->getGenerationID())) | |
418 continue; | |
reveman
2012/12/10 17:58:12
I'm confused. Doesn't this function have to return
qinmin
2012/12/10 22:52:51
it should return false in that case, suppose the p
| |
419 if (static_cast<skia::LazyPixelRef*>(pixel_ref)->PrepareToDecode( | |
420 skia::LazyPixelRef::PrepareParams())) { | |
421 index_to_be_removed.push_back(i); | |
422 } else { | |
423 thread = GetFreeRasterThread(); | |
424 if (thread) { | |
425 has_dispatched_task = true; | |
426 DispatchOneImageDecodingTask(thread, tile, pixel_ref); | |
427 } | |
428 } | |
429 } | |
430 | |
431 for (std::vector<int>::reverse_iterator it = index_to_be_removed.rbegin(); | |
432 it != index_to_be_removed.rend(); ++it) { | |
433 pending_pixel_refs.erase(pending_pixel_refs.begin() + (*it)); | |
reveman
2012/12/10 17:58:12
removing elements from the middle vector is not ve
qinmin
2012/12/10 22:52:51
Switched to list instead
On 2012/12/10 17:58:12,
| |
434 } | |
435 | |
436 if (has_dispatched_task) | |
437 tiles_waiting_for_image_decoding_.push_back(tile); | |
438 | |
439 return has_dispatched_task; | |
440 } | |
441 | |
442 void TileManager::DispatchOneImageDecodingTask(RasterThread* thread, | |
443 scoped_refptr<Tile> tile, | |
444 SkPixelRef* pixel_ref) { | |
445 TRACE_EVENT0("cc", "TileManager::DispatchOneImageDecodingTask"); | |
446 uint32_t pixel_ref_id = pixel_ref->getGenerationID(); | |
447 DCHECK(pending_decode_tasks_.end() == | |
448 pending_decode_tasks_.find(pixel_ref_id)); | |
449 pending_decode_tasks_[pixel_ref_id] = pixel_ref; | |
450 | |
451 thread->PostImageDecodingTaskAndReply( | |
452 FROM_HERE, | |
453 pixel_ref, | |
454 base::Bind(&TileManager::OnImageDecodingTaskCompleted, | |
455 base::Unretained(this), | |
456 tile, | |
457 pixel_ref_id)); | |
458 } | |
459 | |
460 void TileManager::OnImageDecodingTaskCompleted(scoped_refptr<Tile> tile, | |
461 uint32_t pixel_ref_id) { | |
462 TRACE_EVENT0("cc", "TileManager::OnImageDecoded"); | |
463 pending_decode_tasks_.erase(pixel_ref_id); | |
464 | |
465 std::vector<int> tile_index_to_be_removed; | |
466 for (int i = 0; i < tiles_waiting_for_image_decoding_.size(); ++i) { | |
467 std::vector<SkPixelRef*>& pixel_refs = | |
468 tiles_waiting_for_image_decoding_[i]-> | |
469 managed_state().pending_pixel_refs; | |
470 for (std::vector<SkPixelRef*>::iterator pixel_it = | |
471 pixel_refs.begin(); pixel_it != pixel_refs.end(); ++pixel_it) { | |
472 if (pixel_ref_id == (*pixel_it)->getGenerationID()) { | |
473 pixel_refs.erase(pixel_it); | |
474 tile_index_to_be_removed.push_back(i); | |
475 break; | |
476 } | |
477 } | |
478 } | |
479 | |
480 // Tiles are in increasing priority in the image decoding queue. But since | |
481 // we are appending tiles to the back of the rasterize queue, we need to | |
482 // iterate through tiles reversely. | |
483 for (std::vector<int>::reverse_iterator it = | |
484 tile_index_to_be_removed.rbegin(); | |
485 it != tile_index_to_be_removed.rend(); ++it) { | |
486 tiles_that_need_to_be_rasterized_.push_back( | |
487 tiles_waiting_for_image_decoding_[*it]); | |
488 tiles_waiting_for_image_decoding_.erase( | |
489 tiles_waiting_for_image_decoding_.begin() + (*it)); | |
reveman
2012/12/10 17:58:12
again removing elements from the middle of vector.
qinmin
2012/12/10 22:52:51
using list instead
On 2012/12/10 17:58:12, David
| |
490 } | |
491 | |
492 DispatchMoreRasterTasks(); | |
493 } | |
494 | |
364 void TileManager::DispatchOneRasterTask( | 495 void TileManager::DispatchOneRasterTask( |
365 RasterThread* thread, scoped_refptr<Tile> tile) { | 496 RasterThread* thread, scoped_refptr<Tile> tile) { |
366 TRACE_EVENT0("cc", "TileManager::DispatchOneRasterTask"); | 497 TRACE_EVENT0("cc", "TileManager::DispatchOneRasterTask"); |
367 ManagedTileState& managed_tile_state = tile->managed_state(); | 498 ManagedTileState& managed_tile_state = tile->managed_state(); |
368 DCHECK(managed_tile_state.can_use_gpu_memory); | 499 DCHECK(managed_tile_state.can_use_gpu_memory); |
369 scoped_ptr<ResourcePool::Resource> resource = | 500 scoped_ptr<ResourcePool::Resource> resource = |
370 resource_pool_->AcquireResource(tile->tile_size_.size(), tile->format_); | 501 resource_pool_->AcquireResource(tile->tile_size_.size(), tile->format_); |
371 resource_pool_->resource_provider()->acquirePixelBuffer(resource->id()); | 502 resource_pool_->resource_provider()->acquirePixelBuffer(resource->id()); |
372 | 503 |
373 managed_tile_state.resource_is_being_initialized = true; | 504 managed_tile_state.resource_is_being_initialized = true; |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
443 Tile* tile, scoped_ptr<ResourcePool::Resource> resource) { | 574 Tile* tile, scoped_ptr<ResourcePool::Resource> resource) { |
444 ManagedTileState& managed_tile_state = tile->managed_state(); | 575 ManagedTileState& managed_tile_state = tile->managed_state(); |
445 DCHECK(!managed_tile_state.resource); | 576 DCHECK(!managed_tile_state.resource); |
446 managed_tile_state.resource = resource.Pass(); | 577 managed_tile_state.resource = resource.Pass(); |
447 managed_tile_state.resource_is_being_initialized = false; | 578 managed_tile_state.resource_is_being_initialized = false; |
448 // TODO(qinmin): Make this conditional on managed_tile_state.bin == NOW_BIN. | 579 // TODO(qinmin): Make this conditional on managed_tile_state.bin == NOW_BIN. |
449 client_->ScheduleRedraw(); | 580 client_->ScheduleRedraw(); |
450 } | 581 } |
451 | 582 |
452 } | 583 } |
OLD | NEW |