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

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: adding more null checks 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.
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 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
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 }
OLDNEW
« cc/tile_manager.h ('K') | « cc/tile_manager.h ('k') | skia/skia.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698