Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1076)

Side by Side Diff: cc/tile_manager.cc

Issue 11453014: Implement the logic to kick off image decoding jobs for TileManager (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: addressing comments Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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.
reveman 2012/12/07 21:14:54 Why not lazily get information for all types?
qinmin 2012/12/07 23:41:55 So if an image covers several tiles(A,B,C,D) in NO
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
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 std::vector<SkPixelRef*> pixel_refs;
400 if (HasUndecodedImages(tile, pixel_refs)) {
401 tiles_waiting_for_image_decoding_.push_back(tile);
402 DispatchMoreImageDecodingTasks(pixel_refs);
403 } else {
404 DispatchOneRasterTask(thread, tile);
405 }
360 tiles_that_need_to_be_rasterized_.pop_back(); 406 tiles_that_need_to_be_rasterized_.pop_back();
361 } 407 }
362 } 408 }
363 409
410 void TileManager::DispatchMoreImageDecodingTasks(
411 std::vector<SkPixelRef*>& pixel_refs) {
412 if (pixel_refs.empty())
413 return;
414
415 RasterThread* thread = 0;
416 for (std::vector<SkPixelRef*>::iterator it = pixel_refs.begin();
417 it != pixel_refs.end(); ++it) {
418 thread = GetFreeRasterThread();
419 if (!thread)
420 return;
421 DispatchOneImageDecodingTask(thread, *it);
422 }
423 }
424
425 bool TileManager::HasUndecodedImages(Tile* tile,
reveman 2012/12/07 21:14:54 Would it be cleaner to change this function to Dis
qinmin 2012/12/07 23:41:55 ok, combined HasUndecodedImages() and DispatchMore
426 std::vector<SkPixelRef*>& unstarted) {
427 ManagedTileState& managed_state = tile->managed_state();
428 if (!managed_state.has_image_decoding_info)
429 GetImageInformationForTile(tile);
430 while (true) {
431 bool has_removed_pending_tasks = false;
reveman 2012/12/07 21:14:54 I think this nested loop is both hard to read and
qinmin 2012/12/07 23:41:55 Done.
432 for (std::vector<SkPixelRef*>::iterator it =
433 managed_state.pending_pixel_refs.begin();
434 it != managed_state.pending_pixel_refs.end(); ++it) {
435 if (pending_decode_tasks_.end() != pending_decode_tasks_.find(
436 (*it)->getGenerationID()))
437 continue;
438 if (static_cast<skia::LazyPixelRef*>(*it)->PrepareToDecode(
439 skia::LazyPixelRef::PrepareParams())) {
440 managed_state.pending_pixel_refs.erase(it);
441 has_removed_pending_tasks = true;
442 break;
443 } else {
444 unstarted.push_back(*it);
445 }
446 }
447 if (!has_removed_pending_tasks)
448 break;
449 }
450 return !managed_state.pending_pixel_refs.empty();
451 }
452
453 void TileManager::DispatchOneImageDecodingTask(RasterThread* thread,
454 SkPixelRef* pixel_ref) {
455 TRACE_EVENT0("cc", "TileManager::SpawnImageDecodingTask");
reveman 2012/12/07 21:14:54 TileManager::DispatchOneImageDecodingTask
qinmin 2012/12/07 23:41:55 Done.
456 uint32_t pixel_ref_id = pixel_ref->getGenerationID();
457 DCHECK(pending_decode_tasks_.end() ==
458 pending_decode_tasks_.find(pixel_ref_id));
459 pending_decode_tasks_[pixel_ref_id] = pixel_ref;
460
461 // TODO(qinmin): Not sure how we can guarantee SkPixelRef will not get deleted
462 // while it is on the raster thread. In SkBitmap, the SkPixelRef is declared
463 // as mutable.
reveman 2012/12/07 21:14:54 SkPixelRef is owned by the SkPicture, right? Keepi
qinmin 2012/12/07 23:41:55 ok, just holding a scoped_refptr of the tile until
464 thread->PostImageDecodingTaskAndReply(
465 FROM_HERE,
466 pixel_ref,
467 base::Bind(&TileManager::OnImageDecodingTaskCompleted,
468 base::Unretained(this),
469 pixel_ref_id));
470 }
471
472 void TileManager::OnImageDecodingTaskCompleted(uint32_t pixel_ref_id) {
473 TRACE_EVENT0("cc", "TileManager::OnImageDecoded");
474 pending_decode_tasks_.erase(pixel_ref_id);
475 while (true) {
reveman 2012/12/07 21:14:54 this is similar to the function above but you have
qinmin 2012/12/07 23:41:55 Done.
476 bool no_tile_finished_decoding = true;
477 // Tiles are in increasing priority in the image decoding queue. But since
478 // we are appending tiles to the back of the rasterize queue, we need to
479 // iterate through tiles reversely.
480 for (TileVector::reverse_iterator tile_it =
481 tiles_waiting_for_image_decoding_.rbegin();
482 tile_it != tiles_waiting_for_image_decoding_.rend(); ++tile_it) {
483 std::vector<SkPixelRef*>& pixel_refs =
484 (*tile_it)->managed_state().pending_pixel_refs;
485 for (std::vector<SkPixelRef*>::iterator pixel_it =
486 pixel_refs.begin(); pixel_it != pixel_refs.end(); ++pixel_it) {
487 if (pixel_ref_id == (*pixel_it)->getGenerationID()) {
488 pixel_refs.erase(pixel_it);
489 tiles_that_need_to_be_rasterized_.push_back(*tile_it);
490 tiles_waiting_for_image_decoding_.erase(--tile_it.base());
491 no_tile_finished_decoding = false;
492 break;
493 }
494 }
495 if (!no_tile_finished_decoding);
496 break;
497 }
498 if (no_tile_finished_decoding)
499 break;
500 }
501
502 DispatchMoreRasterTasks();
503 }
504
364 void TileManager::DispatchOneRasterTask( 505 void TileManager::DispatchOneRasterTask(
365 RasterThread* thread, scoped_refptr<Tile> tile) { 506 RasterThread* thread, scoped_refptr<Tile> tile) {
366 TRACE_EVENT0("cc", "TileManager::DispatchOneRasterTask"); 507 TRACE_EVENT0("cc", "TileManager::DispatchOneRasterTask");
367 ManagedTileState& managed_tile_state = tile->managed_state(); 508 ManagedTileState& managed_tile_state = tile->managed_state();
368 DCHECK(managed_tile_state.can_use_gpu_memory); 509 DCHECK(managed_tile_state.can_use_gpu_memory);
369 scoped_ptr<ResourcePool::Resource> resource = 510 scoped_ptr<ResourcePool::Resource> resource =
370 resource_pool_->AcquireResource(tile->tile_size_.size(), tile->format_); 511 resource_pool_->AcquireResource(tile->tile_size_.size(), tile->format_);
371 resource_pool_->resource_provider()->acquirePixelBuffer(resource->id()); 512 resource_pool_->resource_provider()->acquirePixelBuffer(resource->id());
372 513
373 managed_tile_state.resource_is_being_initialized = true; 514 managed_tile_state.resource_is_being_initialized = true;
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
443 Tile* tile, scoped_ptr<ResourcePool::Resource> resource) { 584 Tile* tile, scoped_ptr<ResourcePool::Resource> resource) {
444 ManagedTileState& managed_tile_state = tile->managed_state(); 585 ManagedTileState& managed_tile_state = tile->managed_state();
445 DCHECK(!managed_tile_state.resource); 586 DCHECK(!managed_tile_state.resource);
446 managed_tile_state.resource = resource.Pass(); 587 managed_tile_state.resource = resource.Pass();
447 managed_tile_state.resource_is_being_initialized = false; 588 managed_tile_state.resource_is_being_initialized = false;
448 // TODO(qinmin): Make this conditional on managed_tile_state.bin == NOW_BIN. 589 // TODO(qinmin): Make this conditional on managed_tile_state.bin == NOW_BIN.
449 client_->ScheduleRedraw(); 590 client_->ScheduleRedraw();
450 } 591 }
451 592
452 } 593 }
OLDNEW
« cc/picture_pile_impl.cc ('K') | « cc/tile_manager.h ('k') | skia/skia.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698