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/resources/tile_manager.h" | 5 #include "cc/resources/tile_manager.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/json/json_writer.h" | 11 #include "base/json/json_writer.h" |
12 #include "base/logging.h" | 12 #include "base/logging.h" |
13 #include "base/metrics/histogram.h" | 13 #include "base/metrics/histogram.h" |
14 #include "cc/debug/devtools_instrumentation.h" | 14 #include "cc/debug/devtools_instrumentation.h" |
15 #include "cc/debug/traced_value.h" | 15 #include "cc/debug/traced_value.h" |
16 #include "cc/resources/raster_worker_pool.h" | 16 #include "cc/resources/image_raster_worker_pool.h" |
17 #include "cc/resources/resource_pool.h" | 17 #include "cc/resources/pixel_buffer_raster_worker_pool.h" |
18 #include "cc/resources/tile.h" | 18 #include "cc/resources/tile.h" |
19 #include "third_party/skia/include/core/SkDevice.h" | 19 #include "third_party/skia/include/core/SkCanvas.h" |
20 #include "ui/gfx/rect_conversions.h" | 20 #include "ui/gfx/rect_conversions.h" |
21 | 21 |
22 namespace cc { | 22 namespace cc { |
23 | 23 |
24 namespace { | 24 namespace { |
25 | 25 |
26 // If we raster too fast we become upload bound, and pending | |
27 // uploads consume memory. For maximum upload throughput, we would | |
28 // want to allow for upload_throughput * pipeline_time of pending | |
29 // uploads, after which we are just wasting memory. Since we don't | |
30 // know our upload throughput yet, this just caps our memory usage. | |
31 #if defined(OS_ANDROID) | |
32 // For reference, the Nexus10 can upload 1MB in about 2.5ms. | |
33 // Assuming a three frame deep pipeline this implies ~20MB. | |
34 const size_t kMaxPendingUploadBytes = 20 * 1024 * 1024; | |
35 // TODO(epenner): We should remove this upload limit (crbug.com/176197) | |
36 const size_t kMaxPendingUploads = 72; | |
37 #else | |
38 const size_t kMaxPendingUploadBytes = 100 * 1024 * 1024; | |
39 const size_t kMaxPendingUploads = 1000; | |
40 #endif | |
41 | |
42 #if defined(OS_ANDROID) | |
43 const int kMaxNumPendingTasksPerThread = 8; | |
44 #else | |
45 const int kMaxNumPendingTasksPerThread = 40; | |
46 #endif | |
47 | |
48 // Determine bin based on three categories of tiles: things we need now, | 26 // Determine bin based on three categories of tiles: things we need now, |
49 // things we need soon, and eventually. | 27 // things we need soon, and eventually. |
50 inline TileManagerBin BinFromTilePriority(const TilePriority& prio) { | 28 inline TileManagerBin BinFromTilePriority(const TilePriority& prio) { |
51 // The amount of time for which we want to have prepainting coverage. | 29 // The amount of time for which we want to have prepainting coverage. |
52 const float kPrepaintingWindowTimeSeconds = 1.0f; | 30 const float kPrepaintingWindowTimeSeconds = 1.0f; |
53 const float kBackflingGuardDistancePixels = 314.0f; | 31 const float kBackflingGuardDistancePixels = 314.0f; |
54 | 32 |
55 if (prio.time_to_visible_in_seconds == 0) | 33 if (prio.time_to_visible_in_seconds == 0) |
56 return NOW_BIN; | 34 return NOW_BIN; |
57 | 35 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
105 } | 83 } |
106 | 84 |
107 // static | 85 // static |
108 scoped_ptr<TileManager> TileManager::Create( | 86 scoped_ptr<TileManager> TileManager::Create( |
109 TileManagerClient* client, | 87 TileManagerClient* client, |
110 ResourceProvider* resource_provider, | 88 ResourceProvider* resource_provider, |
111 size_t num_raster_threads, | 89 size_t num_raster_threads, |
112 bool use_color_estimator, | 90 bool use_color_estimator, |
113 RenderingStatsInstrumentation* rendering_stats_instrumentation, | 91 RenderingStatsInstrumentation* rendering_stats_instrumentation, |
114 bool use_map_image) { | 92 bool use_map_image) { |
115 scoped_ptr<RasterWorkerPool> raster_worker_pool = | 93 return make_scoped_ptr( |
116 RasterWorkerPool::Create(num_raster_threads); | 94 new TileManager(client, |
117 return make_scoped_ptr(new TileManager(client, | 95 resource_provider, |
118 resource_provider, | 96 use_map_image ? |
119 raster_worker_pool.Pass(), | 97 ImageRasterWorkerPool::Create( |
120 num_raster_threads, | 98 resource_provider, num_raster_threads) : |
121 use_color_estimator, | 99 PixelBufferRasterWorkerPool::Create( |
122 rendering_stats_instrumentation, | 100 resource_provider, num_raster_threads), |
123 use_map_image)); | 101 num_raster_threads, |
102 use_color_estimator, | |
103 rendering_stats_instrumentation)); | |
124 } | 104 } |
125 | 105 |
126 TileManager::TileManager( | 106 TileManager::TileManager( |
127 TileManagerClient* client, | 107 TileManagerClient* client, |
128 ResourceProvider* resource_provider, | 108 ResourceProvider* resource_provider, |
129 scoped_ptr<RasterWorkerPool> raster_worker_pool, | 109 scoped_ptr<RasterWorkerPool> raster_worker_pool, |
130 size_t num_raster_threads, | 110 size_t num_raster_threads, |
131 bool use_color_estimator, | 111 bool use_color_estimator, |
132 RenderingStatsInstrumentation* rendering_stats_instrumentation, | 112 RenderingStatsInstrumentation* rendering_stats_instrumentation) |
133 bool use_map_image) | |
134 : client_(client), | 113 : client_(client), |
135 resource_pool_(ResourcePool::Create(resource_provider)), | 114 resource_pool_(ResourcePool::Create(resource_provider)), |
136 raster_worker_pool_(raster_worker_pool.Pass()), | 115 raster_worker_pool_(raster_worker_pool.Pass()), |
137 manage_tiles_pending_(false), | 116 manage_tiles_pending_(false), |
138 bytes_pending_upload_(0), | |
139 has_performed_uploads_since_last_flush_(false), | |
140 ever_exceeded_memory_budget_(false), | 117 ever_exceeded_memory_budget_(false), |
141 rendering_stats_instrumentation_(rendering_stats_instrumentation), | 118 rendering_stats_instrumentation_(rendering_stats_instrumentation), |
142 use_color_estimator_(use_color_estimator), | 119 use_color_estimator_(use_color_estimator), |
143 did_initialize_visible_tile_(false), | 120 did_initialize_visible_tile_(false) { |
144 max_pending_tasks_(kMaxNumPendingTasksPerThread * num_raster_threads) { | |
145 raster_worker_pool_->SetClient(this); | |
146 } | 121 } |
147 | 122 |
148 TileManager::~TileManager() { | 123 TileManager::~TileManager() { |
149 // Reset global state and manage. This should cause | 124 // Reset global state and manage. This should cause |
150 // our memory usage to drop to zero. | 125 // our memory usage to drop to zero. |
151 global_state_ = GlobalStateThatImpactsTilePriority(); | 126 global_state_ = GlobalStateThatImpactsTilePriority(); |
152 AssignGpuMemoryToTiles(); | 127 AssignGpuMemoryToTiles(); |
153 // This should finish all pending tasks and release any uninitialized | 128 // This should finish all pending tasks and release any uninitialized |
154 // resources. | 129 // resources. |
155 raster_worker_pool_->Shutdown(); | 130 raster_worker_pool_->Shutdown(); |
156 AbortPendingTileUploads(); | |
157 DCHECK_EQ(0u, tiles_with_pending_upload_.size()); | |
158 DCHECK_EQ(0u, tiles_.size()); | 131 DCHECK_EQ(0u, tiles_.size()); |
159 } | 132 } |
160 | 133 |
161 void TileManager::SetGlobalState( | 134 void TileManager::SetGlobalState( |
162 const GlobalStateThatImpactsTilePriority& global_state) { | 135 const GlobalStateThatImpactsTilePriority& global_state) { |
163 global_state_ = global_state; | 136 global_state_ = global_state; |
164 resource_pool_->SetMaxMemoryUsageBytes( | 137 resource_pool_->SetMaxMemoryUsageBytes( |
165 global_state_.memory_limit_in_bytes, | 138 global_state_.memory_limit_in_bytes, |
166 global_state_.unused_memory_limit_in_bytes); | 139 global_state_.unused_memory_limit_in_bytes); |
167 ScheduleManageTiles(); | 140 ScheduleManageTiles(); |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
314 | 287 |
315 TRACE_EVENT_INSTANT1( | 288 TRACE_EVENT_INSTANT1( |
316 "cc", "DidManage", TRACE_EVENT_SCOPE_THREAD, | 289 "cc", "DidManage", TRACE_EVENT_SCOPE_THREAD, |
317 "state", TracedValue::FromValue(BasicStateAsValue().release())); | 290 "state", TracedValue::FromValue(BasicStateAsValue().release())); |
318 | 291 |
319 // Finally, schedule rasterizer tasks. | 292 // Finally, schedule rasterizer tasks. |
320 ScheduleTasks(); | 293 ScheduleTasks(); |
321 } | 294 } |
322 | 295 |
323 void TileManager::CheckForCompletedTileUploads() { | 296 void TileManager::CheckForCompletedTileUploads() { |
324 while (!tiles_with_pending_upload_.empty()) { | 297 raster_worker_pool_->CheckForCompletedTasks(); |
325 Tile* tile = tiles_with_pending_upload_.front(); | |
326 DCHECK(tile->tile_version().resource_); | |
327 | 298 |
328 // Set pixel tasks complete in the order they are posted. | 299 if (client_->ShouldForceTileUploadsRequiredForActivationToComplete()) { |
enne (OOO)
2013/05/30 19:38:31
style nit: early out here instead?
reveman
2013/05/30 23:25:18
Done.
| |
329 if (!resource_pool_->resource_provider()->DidSetPixelsComplete( | 300 TileSet initialized_tiles; |
330 tile->tile_version().resource_->id())) { | 301 for (TileSet::iterator it = |
331 break; | 302 tiles_that_need_to_be_initialized_for_activation_.begin(); |
303 it != tiles_that_need_to_be_initialized_for_activation_.end(); | |
304 ++it) { | |
305 Tile* tile = *it; | |
306 if (!tile->managed_state().raster_task.is_null() && | |
307 tile->tile_version().memory_state_ == USING_UNRELEASABLE_MEMORY && | |
308 !tile->tile_version().forced_upload_) { | |
309 if (!raster_worker_pool_->ForceUploadToComplete( | |
310 tile->managed_state().raster_task)) | |
311 continue; | |
312 | |
313 // Setting |forced_upload_| to true makes this tile ready to draw. | |
314 tile->tile_version().forced_upload_ = true; | |
315 initialized_tiles.insert(tile); | |
316 } | |
332 } | 317 } |
333 | 318 |
334 // It's now safe to release the pixel buffer. | 319 for (TileSet::iterator it = initialized_tiles.begin(); |
335 resource_pool_->resource_provider()->ReleasePixelBuffer( | 320 it != initialized_tiles.end(); |
336 tile->tile_version().resource_->id()); | 321 ++it) { |
337 | 322 Tile* tile = *it; |
338 bytes_pending_upload_ -= tile->bytes_consumed_if_allocated(); | |
339 bool was_forced = tile->tile_version().forced_upload_; | |
340 // Reset forced_upload_ since we now got the upload completed notification. | |
341 tile->tile_version().forced_upload_ = false; | |
342 tile->tile_version().memory_state_ = USING_RELEASABLE_MEMORY; | |
343 if (!was_forced) | |
344 DidFinishTileInitialization(tile); | 323 DidFinishTileInitialization(tile); |
345 | 324 DCHECK(tile->tile_version().IsReadyToDraw()); |
346 tiles_with_pending_upload_.pop(); | 325 } |
347 } | |
348 | |
349 ScheduleTasks(); | |
350 } | |
351 | |
352 void TileManager::AbortPendingTileUploads() { | |
353 while (!tiles_with_pending_upload_.empty()) { | |
354 Tile* tile = tiles_with_pending_upload_.front(); | |
355 DCHECK(tile->tile_version().resource_); | |
356 | |
357 resource_pool_->resource_provider()->AbortSetPixels( | |
358 tile->tile_version().resource_->id()); | |
359 resource_pool_->resource_provider()->ReleasePixelBuffer( | |
360 tile->tile_version().resource_->id()); | |
361 tile->tile_version().memory_state_ = USING_RELEASABLE_MEMORY; | |
362 | |
363 FreeResourcesForTile(tile); | |
364 | |
365 bytes_pending_upload_ -= tile->bytes_consumed_if_allocated(); | |
366 tiles_with_pending_upload_.pop(); | |
367 } | 326 } |
368 } | 327 } |
369 | 328 |
370 void TileManager::ForceTileUploadToComplete(Tile* tile) { | |
371 DCHECK(tile); | |
372 if (tile->tile_version().resource_ && | |
373 tile->tile_version().memory_state_ == USING_UNRELEASABLE_MEMORY && | |
374 !tile->tile_version().forced_upload_) { | |
375 resource_pool_->resource_provider()-> | |
376 ForceSetPixelsToComplete(tile->tile_version().resource_->id()); | |
377 | |
378 // We have to set the memory state to be unreleasable, to ensure | |
379 // that the tile will not be freed until we get the upload finished | |
380 // notification. However, setting |forced_upload_| to true makes | |
381 // this tile ready to draw. | |
382 tile->tile_version().memory_state_ = USING_UNRELEASABLE_MEMORY; | |
383 tile->tile_version().forced_upload_ = true; | |
384 DidFinishTileInitialization(tile); | |
385 DCHECK(tile->tile_version().IsReadyToDraw()); | |
386 } | |
387 } | |
388 | |
389 void TileManager::GetMemoryStats( | 329 void TileManager::GetMemoryStats( |
390 size_t* memory_required_bytes, | 330 size_t* memory_required_bytes, |
391 size_t* memory_nice_to_have_bytes, | 331 size_t* memory_nice_to_have_bytes, |
392 size_t* memory_used_bytes) const { | 332 size_t* memory_used_bytes) const { |
393 *memory_required_bytes = 0; | 333 *memory_required_bytes = 0; |
394 *memory_nice_to_have_bytes = 0; | 334 *memory_nice_to_have_bytes = 0; |
395 *memory_used_bytes = 0; | 335 *memory_used_bytes = 0; |
396 for (TileVector::const_iterator it = tiles_.begin(); | 336 for (TileVector::const_iterator it = tiles_.begin(); |
397 it != tiles_.end(); | 337 it != tiles_.end(); |
398 ++it) { | 338 ++it) { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
447 } | 387 } |
448 | 388 |
449 void TileManager::AddRequiredTileForActivation(Tile* tile) { | 389 void TileManager::AddRequiredTileForActivation(Tile* tile) { |
450 DCHECK(std::find(tiles_that_need_to_be_initialized_for_activation_.begin(), | 390 DCHECK(std::find(tiles_that_need_to_be_initialized_for_activation_.begin(), |
451 tiles_that_need_to_be_initialized_for_activation_.end(), | 391 tiles_that_need_to_be_initialized_for_activation_.end(), |
452 tile) == | 392 tile) == |
453 tiles_that_need_to_be_initialized_for_activation_.end()); | 393 tiles_that_need_to_be_initialized_for_activation_.end()); |
454 tiles_that_need_to_be_initialized_for_activation_.insert(tile); | 394 tiles_that_need_to_be_initialized_for_activation_.insert(tile); |
455 } | 395 } |
456 | 396 |
457 void TileManager::DidFinishDispatchingWorkerPoolCompletionCallbacks() { | |
458 // If a flush is needed, do it now before starting to dispatch more tasks. | |
459 if (has_performed_uploads_since_last_flush_) { | |
460 resource_pool_->resource_provider()->ShallowFlushIfSupported(); | |
461 has_performed_uploads_since_last_flush_ = false; | |
462 } | |
463 | |
464 ScheduleTasks(); | |
465 } | |
466 | |
467 void TileManager::AssignGpuMemoryToTiles() { | 397 void TileManager::AssignGpuMemoryToTiles() { |
468 TRACE_EVENT0("cc", "TileManager::AssignGpuMemoryToTiles"); | 398 TRACE_EVENT0("cc", "TileManager::AssignGpuMemoryToTiles"); |
469 size_t unreleasable_bytes = 0; | 399 size_t unreleasable_bytes = 0; |
470 | 400 |
471 // Now give memory out to the tiles until we're out, and build | 401 // Now give memory out to the tiles until we're out, and build |
472 // the needs-to-be-rasterized queue. | 402 // the needs-to-be-rasterized queue. |
473 tiles_that_need_to_be_rasterized_.clear(); | 403 tiles_that_need_to_be_rasterized_.clear(); |
474 tiles_that_need_to_be_initialized_for_activation_.clear(); | 404 tiles_that_need_to_be_initialized_for_activation_.clear(); |
475 | 405 |
476 // By clearing the tiles_that_need_to_be_rasterized_ vector list | 406 // By clearing the tiles_that_need_to_be_rasterized_ vector list |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
545 // 2. Tile with unreleasable memory could otherwise incorrectly | 475 // 2. Tile with unreleasable memory could otherwise incorrectly |
546 // be added as it's not affected by |bytes_allocatable|. | 476 // be added as it's not affected by |bytes_allocatable|. |
547 if (higher_priority_tile_oomed) | 477 if (higher_priority_tile_oomed) |
548 continue; | 478 continue; |
549 | 479 |
550 if (!tile_version.resource_) | 480 if (!tile_version.resource_) |
551 tiles_that_need_to_be_rasterized_.push_back(tile); | 481 tiles_that_need_to_be_rasterized_.push_back(tile); |
552 | 482 |
553 if (!tile_version.resource_ && tile->required_for_activation()) | 483 if (!tile_version.resource_ && tile->required_for_activation()) |
554 AddRequiredTileForActivation(tile); | 484 AddRequiredTileForActivation(tile); |
555 | |
556 if (tile_version.memory_state_ == USING_UNRELEASABLE_MEMORY && | |
557 tile->required_for_activation()) { | |
558 // If after rasterizing, this tile has become required or the client has | |
559 // changed its mind about forcing tiles, do that now. | |
560 if (!tile->tile_version().forced_upload_ && | |
561 client_->ShouldForceTileUploadsRequiredForActivationToComplete()) { | |
562 ForceTileUploadToComplete(tile); | |
563 } | |
564 } | |
565 } | 485 } |
566 | 486 |
567 // In OOM situation, we iterate tiles_, remove the memory for active tree | 487 // In OOM situation, we iterate tiles_, remove the memory for active tree |
568 // and not the now bin. And give them to bytes_oom_in_now_bin_on_pending_tree | 488 // and not the now bin. And give them to bytes_oom_in_now_bin_on_pending_tree |
569 if (!tiles_requiring_memory_but_oomed.empty()) { | 489 if (!tiles_requiring_memory_but_oomed.empty()) { |
570 size_t bytes_freed = 0; | 490 size_t bytes_freed = 0; |
571 for (TileVector::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { | 491 for (TileVector::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { |
572 Tile* tile = *it; | 492 Tile* tile = *it; |
573 ManagedTileState& mts = tile->managed_state(); | 493 ManagedTileState& mts = tile->managed_state(); |
574 ManagedTileState::TileVersion& tile_version = tile->tile_version(); | 494 ManagedTileState::TileVersion& tile_version = tile->tile_version(); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
626 DCHECK_NE(USING_UNRELEASABLE_MEMORY, tile->tile_version().memory_state_); | 546 DCHECK_NE(USING_UNRELEASABLE_MEMORY, tile->tile_version().memory_state_); |
627 if (tile->tile_version().resource_) { | 547 if (tile->tile_version().resource_) { |
628 resource_pool_->ReleaseResource( | 548 resource_pool_->ReleaseResource( |
629 tile->tile_version().resource_.Pass()); | 549 tile->tile_version().resource_.Pass()); |
630 } | 550 } |
631 tile->tile_version().memory_state_ = NOT_ALLOWED_TO_USE_MEMORY; | 551 tile->tile_version().memory_state_ = NOT_ALLOWED_TO_USE_MEMORY; |
632 } | 552 } |
633 | 553 |
634 void TileManager::ScheduleTasks() { | 554 void TileManager::ScheduleTasks() { |
635 TRACE_EVENT0("cc", "TileManager::ScheduleTasks"); | 555 TRACE_EVENT0("cc", "TileManager::ScheduleTasks"); |
636 RasterWorkerPool::Task::Queue tasks; | 556 RasterWorkerPool::RasterTask::Queue tasks; |
637 | |
638 size_t bytes_pending_upload = bytes_pending_upload_; | |
639 unsigned pending_tasks = 0; | |
640 | 557 |
641 // Build a new task queue containing all task currently needed. Tasks | 558 // Build a new task queue containing all task currently needed. Tasks |
642 // are added in order of priority, highest priority task first. | 559 // are added in order of priority, highest priority task first. |
643 for (TileVector::iterator it = tiles_that_need_to_be_rasterized_.begin(); | 560 for (TileVector::iterator it = tiles_that_need_to_be_rasterized_.begin(); |
644 it != tiles_that_need_to_be_rasterized_.end(); | 561 it != tiles_that_need_to_be_rasterized_.end(); |
645 ++it) { | 562 ++it) { |
646 Tile* tile = *it; | 563 Tile* tile = *it; |
647 ManagedTileState& mts = tile->managed_state(); | 564 ManagedTileState& mts = tile->managed_state(); |
648 | 565 |
649 // Skip tile if determined to not require resource. | 566 DCHECK(tile->tile_version().requires_resource()); |
650 if (!tile->tile_version().requires_resource()) | 567 DCHECK(!tile->tile_version().resource_); |
651 continue; | |
652 | |
653 // Skip tile if already rasterized. | |
654 if (tile->tile_version().resource_) | |
655 continue; | |
656 | |
657 // TODO(reveman): Remove throttling based on max pending tasks. | |
658 if (pending_tasks >= max_pending_tasks_) | |
659 break; | |
660 | |
661 // TODO(reveman): Remove throttling based on max pending uploads. | |
662 if (tiles_with_pending_upload_.size() >= kMaxPendingUploads) | |
663 break; | |
664 | |
665 // TODO(reveman): Throttle based on shared memory usage rather | |
666 // than bytes pending upload. | |
667 size_t new_bytes_pending = bytes_pending_upload; | |
668 new_bytes_pending += tile->bytes_consumed_if_allocated(); | |
669 if (new_bytes_pending > kMaxPendingUploadBytes) | |
670 break; | |
671 bytes_pending_upload = new_bytes_pending; | |
672 | 568 |
673 // Create raster task for this tile if necessary. | 569 // Create raster task for this tile if necessary. |
674 if (mts.raster_task.is_null()) | 570 if (mts.raster_task.is_null()) |
675 mts.raster_task = CreateRasterTask(tile); | 571 mts.raster_task = CreateRasterTask(tile); |
676 | 572 |
677 // Finally append raster task. | 573 // Finally append raster task. |
678 tasks.Append(mts.raster_task); | 574 tasks.Append(mts.raster_task); |
679 pending_tasks++; | |
680 } | 575 } |
681 | 576 |
682 if (!tasks.empty()) { | 577 // Schedule running of |tasks|. This replaces any previously |
683 RasterWorkerPool::Task root(&tasks); | 578 // scheduled tasks and effectively cancels all tasks not present |
684 | 579 // in |tasks|. |
685 // Schedule running of |tasks|. This replaces any previously | 580 raster_worker_pool_->ScheduleTasks(&tasks); |
686 // scheduled tasks and effectively cancels all tasks not present | |
687 // in |tasks|. | |
688 raster_worker_pool_->ScheduleTasks(&root); | |
689 } else { | |
690 raster_worker_pool_->ScheduleTasks(NULL); | |
691 } | |
692 | |
693 if (did_initialize_visible_tile_) { | |
694 did_initialize_visible_tile_ = false; | |
695 client_->DidInitializeVisibleTile(); | |
696 } | |
697 } | 581 } |
698 | 582 |
699 RasterWorkerPool::Task TileManager::CreateImageDecodeTask( | 583 RasterWorkerPool::Task TileManager::CreateImageDecodeTask( |
700 Tile* tile, skia::LazyPixelRef* pixel_ref) { | 584 Tile* tile, skia::LazyPixelRef* pixel_ref) { |
701 TRACE_EVENT0("cc", "TileManager::CreateImageDecodeTask"); | 585 TRACE_EVENT0("cc", "TileManager::CreateImageDecodeTask"); |
702 | 586 |
703 return RasterWorkerPool::Task( | 587 return RasterWorkerPool::Task( |
704 base::Bind(&TileManager::RunImageDecodeTask, | 588 base::Bind(&TileManager::RunImageDecodeTask, |
705 pixel_ref, | 589 pixel_ref, |
706 tile->layer_id(), | 590 tile->layer_id(), |
707 rendering_stats_instrumentation_), | 591 rendering_stats_instrumentation_), |
708 base::Bind(&TileManager::OnImageDecodeTaskCompleted, | 592 base::Bind(&TileManager::OnImageDecodeTaskCompleted, |
709 base::Unretained(this), | 593 base::Unretained(this), |
710 make_scoped_refptr(tile), | 594 make_scoped_refptr(tile), |
711 pixel_ref->getGenerationID())); | 595 pixel_ref->getGenerationID())); |
712 } | 596 } |
713 | 597 |
714 void TileManager::OnImageDecodeTaskCompleted(scoped_refptr<Tile> tile, | 598 void TileManager::OnImageDecodeTaskCompleted(scoped_refptr<Tile> tile, |
715 uint32_t pixel_ref_id, | 599 uint32_t pixel_ref_id) { |
716 bool was_canceled) { | |
717 TRACE_EVENT0("cc", "TileManager::OnImageDecodeTaskCompleted"); | 600 TRACE_EVENT0("cc", "TileManager::OnImageDecodeTaskCompleted"); |
718 DCHECK(pending_decode_tasks_.find(pixel_ref_id) != | 601 DCHECK(pending_decode_tasks_.find(pixel_ref_id) != |
719 pending_decode_tasks_.end()); | 602 pending_decode_tasks_.end()); |
720 pending_decode_tasks_.erase(pixel_ref_id); | 603 pending_decode_tasks_.erase(pixel_ref_id); |
721 } | 604 } |
722 | 605 |
723 TileManager::RasterTaskMetadata TileManager::GetRasterTaskMetadata( | 606 TileManager::RasterTaskMetadata TileManager::GetRasterTaskMetadata( |
724 const Tile& tile) const { | 607 const Tile& tile) const { |
725 RasterTaskMetadata metadata; | 608 RasterTaskMetadata metadata; |
726 const ManagedTileState& mts = tile.managed_state(); | 609 const ManagedTileState& mts = tile.managed_state(); |
727 metadata.is_tile_in_pending_tree_now_bin = | 610 metadata.is_tile_in_pending_tree_now_bin = |
728 mts.tree_bin[PENDING_TREE] == NOW_BIN; | 611 mts.tree_bin[PENDING_TREE] == NOW_BIN; |
729 metadata.tile_resolution = mts.resolution; | 612 metadata.tile_resolution = mts.resolution; |
730 metadata.layer_id = tile.layer_id(); | 613 metadata.layer_id = tile.layer_id(); |
731 metadata.tile_id = &tile; | 614 metadata.tile_id = &tile; |
732 metadata.source_frame_number = tile.source_frame_number(); | 615 metadata.source_frame_number = tile.source_frame_number(); |
733 return metadata; | 616 return metadata; |
734 } | 617 } |
735 | 618 |
736 RasterWorkerPool::Task TileManager::CreateRasterTask(Tile* tile) { | 619 RasterWorkerPool::RasterTask TileManager::CreateRasterTask(Tile* tile) { |
737 TRACE_EVENT0("cc", "TileManager::CreateRasterTask"); | 620 TRACE_EVENT0("cc", "TileManager::CreateRasterTask"); |
738 | 621 |
739 scoped_ptr<ResourcePool::Resource> resource = | 622 scoped_ptr<ResourcePool::Resource> resource = |
740 resource_pool_->AcquireResource( | 623 resource_pool_->AcquireResource( |
741 tile->tile_size_.size(), | 624 tile->tile_size_.size(), |
742 tile->tile_version().resource_format_); | 625 tile->tile_version().resource_format_); |
743 resource_pool_->resource_provider()->AcquirePixelBuffer(resource->id()); | 626 const Resource* const_resource = resource.get(); |
744 | 627 |
745 DCHECK_EQ(CAN_USE_MEMORY, tile->tile_version().memory_state_); | 628 DCHECK_EQ(CAN_USE_MEMORY, tile->tile_version().memory_state_); |
746 tile->tile_version().memory_state_ = USING_UNRELEASABLE_MEMORY; | 629 tile->tile_version().memory_state_ = USING_UNRELEASABLE_MEMORY; |
630 tile->tile_version().resource_id_ = resource->id(); | |
747 | 631 |
748 PicturePileImpl::Analysis* analysis = new PicturePileImpl::Analysis; | 632 PicturePileImpl::Analysis* analysis = new PicturePileImpl::Analysis; |
749 | 633 |
750 // MapPixelBuffer() returns NULL if context was lost at the time | |
751 // AcquirePixelBuffer() was called. For simplicity we still create | |
752 // a raster task that is essentially a noop in these situations. | |
753 uint8* buffer = resource_pool_->resource_provider()->MapPixelBuffer( | |
754 resource->id()); | |
755 | |
756 // Create and queue all image decode tasks that this tile depends on. | 634 // Create and queue all image decode tasks that this tile depends on. |
757 RasterWorkerPool::Task::Queue decode_tasks; | 635 RasterWorkerPool::Task::Set decode_tasks; |
758 for (PicturePileImpl::PixelRefIterator iter(tile->content_rect(), | 636 for (PicturePileImpl::PixelRefIterator iter(tile->content_rect(), |
759 tile->contents_scale(), | 637 tile->contents_scale(), |
760 tile->picture_pile()); | 638 tile->picture_pile()); |
761 iter; ++iter) { | 639 iter; ++iter) { |
762 skia::LazyPixelRef* pixel_ref = *iter; | 640 skia::LazyPixelRef* pixel_ref = *iter; |
763 uint32_t id = pixel_ref->getGenerationID(); | 641 uint32_t id = pixel_ref->getGenerationID(); |
764 | 642 |
765 // Append existing image decode task if available. | 643 // Append existing image decode task if available. |
766 PixelRefMap::iterator decode_task_it = pending_decode_tasks_.find(id); | 644 PixelRefMap::iterator decode_task_it = pending_decode_tasks_.find(id); |
767 if (decode_task_it != pending_decode_tasks_.end()) { | 645 if (decode_task_it != pending_decode_tasks_.end()) { |
768 decode_tasks.Append(decode_task_it->second); | 646 decode_tasks.Insert(decode_task_it->second); |
769 continue; | 647 continue; |
770 } | 648 } |
771 | 649 |
772 // TODO(qinmin): passing correct image size to PrepareToDecode(). | 650 // TODO(qinmin): passing correct image size to PrepareToDecode(). |
773 if (pixel_ref->PrepareToDecode(skia::LazyPixelRef::PrepareParams())) { | 651 if (pixel_ref->PrepareToDecode(skia::LazyPixelRef::PrepareParams())) { |
774 rendering_stats_instrumentation_->IncrementDeferredImageCacheHitCount(); | 652 rendering_stats_instrumentation_->IncrementDeferredImageCacheHitCount(); |
775 continue; | 653 continue; |
776 } | 654 } |
777 | 655 |
778 // Create and append new image decode task for this pixel ref. | 656 // Create and append new image decode task for this pixel ref. |
779 RasterWorkerPool::Task decode_task = CreateImageDecodeTask( | 657 RasterWorkerPool::Task decode_task = CreateImageDecodeTask( |
780 tile, pixel_ref); | 658 tile, pixel_ref); |
781 decode_tasks.Append(decode_task); | 659 decode_tasks.Insert(decode_task); |
782 pending_decode_tasks_[id] = decode_task; | 660 pending_decode_tasks_[id] = decode_task; |
783 } | 661 } |
784 | 662 |
785 return RasterWorkerPool::PictureTask( | 663 return RasterWorkerPool::RasterTask( |
786 tile->picture_pile(), | 664 tile->picture_pile(), |
665 const_resource, | |
787 base::Bind(&TileManager::RunAnalyzeAndRasterTask, | 666 base::Bind(&TileManager::RunAnalyzeAndRasterTask, |
788 base::Bind(&TileManager::RunAnalyzeTask, | 667 base::Bind(&TileManager::RunAnalyzeTask, |
789 analysis, | 668 analysis, |
790 tile->content_rect(), | 669 tile->content_rect(), |
791 tile->contents_scale(), | 670 tile->contents_scale(), |
792 use_color_estimator_, | 671 use_color_estimator_, |
793 GetRasterTaskMetadata(*tile), | 672 GetRasterTaskMetadata(*tile), |
794 rendering_stats_instrumentation_), | 673 rendering_stats_instrumentation_), |
795 base::Bind(&TileManager::RunRasterTask, | 674 base::Bind(&TileManager::RunRasterTask, |
796 buffer, | |
797 analysis, | 675 analysis, |
798 tile->content_rect(), | 676 tile->content_rect(), |
799 tile->contents_scale(), | 677 tile->contents_scale(), |
800 GetRasterTaskMetadata(*tile), | 678 GetRasterTaskMetadata(*tile), |
801 rendering_stats_instrumentation_)), | 679 rendering_stats_instrumentation_)), |
802 base::Bind(&TileManager::OnRasterTaskCompleted, | 680 base::Bind(&TileManager::OnRasterTaskCompleted, |
803 base::Unretained(this), | 681 base::Unretained(this), |
804 make_scoped_refptr(tile), | 682 make_scoped_refptr(tile), |
805 base::Passed(&resource), | 683 base::Passed(&resource), |
806 base::Owned(analysis)), | 684 base::Owned(analysis)), |
807 &decode_tasks); | 685 &decode_tasks); |
808 } | 686 } |
809 | 687 |
810 void TileManager::OnRasterTaskCompleted( | 688 void TileManager::OnRasterTaskCompleted( |
811 scoped_refptr<Tile> tile, | 689 scoped_refptr<Tile> tile, |
812 scoped_ptr<ResourcePool::Resource> resource, | 690 scoped_ptr<ResourcePool::Resource> resource, |
813 PicturePileImpl::Analysis* analysis, | 691 PicturePileImpl::Analysis* analysis, |
814 bool was_canceled) { | 692 bool was_canceled) { |
815 TRACE_EVENT0("cc", "TileManager::OnRasterTaskCompleted"); | 693 TRACE_EVENT0("cc", "TileManager::OnRasterTaskCompleted"); |
816 | 694 |
817 ManagedTileState& mts = tile->managed_state(); | 695 ManagedTileState& mts = tile->managed_state(); |
818 DCHECK(!mts.raster_task.is_null()); | 696 DCHECK(!mts.raster_task.is_null()); |
819 mts.raster_task.Reset(); | 697 mts.raster_task.Reset(); |
820 | 698 |
821 // Tile resources can't be freed until upload has completed. | 699 // Tile resources can't be freed until task has completed. |
822 DCHECK_EQ(USING_UNRELEASABLE_MEMORY, tile->tile_version().memory_state_); | 700 DCHECK_EQ(USING_UNRELEASABLE_MEMORY, tile->tile_version().memory_state_); |
823 | 701 |
824 // Release raster resources. | |
825 resource_pool_->resource_provider()->UnmapPixelBuffer(resource->id()); | |
826 | |
827 if (was_canceled) { | 702 if (was_canceled) { |
828 tile->tile_version().memory_state_ = CAN_USE_MEMORY; | 703 tile->tile_version().memory_state_ = CAN_USE_MEMORY; |
829 resource_pool_->resource_provider()->ReleasePixelBuffer(resource->id()); | |
830 resource_pool_->ReleaseResource(resource.Pass()); | 704 resource_pool_->ReleaseResource(resource.Pass()); |
831 return; | 705 return; |
832 } | 706 } |
833 | 707 |
834 mts.picture_pile_analysis = *analysis; | 708 mts.picture_pile_analysis = *analysis; |
835 mts.picture_pile_analyzed = true; | 709 mts.picture_pile_analyzed = true; |
836 | 710 |
837 if (analysis->is_solid_color) { | 711 if (analysis->is_solid_color) { |
838 tile->tile_version().set_solid_color(analysis->solid_color); | 712 tile->tile_version().set_solid_color(analysis->solid_color); |
839 resource_pool_->resource_provider()->ReleasePixelBuffer(resource->id()); | |
840 resource_pool_->ReleaseResource(resource.Pass()); | 713 resource_pool_->ReleaseResource(resource.Pass()); |
841 DidFinishTileInitialization(tile); | 714 } else { |
842 return; | 715 tile->tile_version().memory_state_ = USING_RELEASABLE_MEMORY; |
716 tile->tile_version().resource_ = resource.Pass(); | |
843 } | 717 } |
844 | 718 |
845 resource_pool_->resource_provider()->BeginSetPixels(resource->id()); | 719 DidFinishTileInitialization(tile); |
846 has_performed_uploads_since_last_flush_ = true; | |
847 | |
848 tile->tile_version().resource_ = resource.Pass(); | |
849 | |
850 bytes_pending_upload_ += tile->bytes_consumed_if_allocated(); | |
851 tiles_with_pending_upload_.push(tile); | |
852 | |
853 if (tile->required_for_activation() && | |
854 client_->ShouldForceTileUploadsRequiredForActivationToComplete()) | |
855 ForceTileUploadToComplete(tile); | |
856 } | 720 } |
857 | 721 |
858 void TileManager::DidFinishTileInitialization(Tile* tile) { | 722 void TileManager::DidFinishTileInitialization(Tile* tile) { |
859 if (tile->priority(ACTIVE_TREE).distance_to_visible_in_pixels == 0) | 723 if (tile->priority(ACTIVE_TREE).distance_to_visible_in_pixels == 0) |
860 did_initialize_visible_tile_ = true; | 724 did_initialize_visible_tile_ = true; |
861 if (tile->required_for_activation()) { | 725 if (tile->required_for_activation()) { |
862 // It's possible that a tile required for activation is not in this list | 726 // It's possible that a tile required for activation is not in this list |
863 // if it was marked as being required after being dispatched for | 727 // if it was marked as being required after being dispatched for |
864 // rasterization but before AssignGPUMemory was called again. | 728 // rasterization but before AssignGPUMemory was called again. |
865 tiles_that_need_to_be_initialized_for_activation_.erase(tile); | 729 tiles_that_need_to_be_initialized_for_activation_.erase(tile); |
(...skipping 15 matching lines...) Expand all Loading... | |
881 TRACE_EVENT0("cc", "TileManager::RunImageDecodeTask"); | 745 TRACE_EVENT0("cc", "TileManager::RunImageDecodeTask"); |
882 devtools_instrumentation::ScopedLayerTask image_decode_task( | 746 devtools_instrumentation::ScopedLayerTask image_decode_task( |
883 devtools_instrumentation::kImageDecodeTask, layer_id); | 747 devtools_instrumentation::kImageDecodeTask, layer_id); |
884 base::TimeTicks start_time = stats_instrumentation->StartRecording(); | 748 base::TimeTicks start_time = stats_instrumentation->StartRecording(); |
885 pixel_ref->Decode(); | 749 pixel_ref->Decode(); |
886 base::TimeDelta duration = stats_instrumentation->EndRecording(start_time); | 750 base::TimeDelta duration = stats_instrumentation->EndRecording(start_time); |
887 stats_instrumentation->AddDeferredImageDecode(duration); | 751 stats_instrumentation->AddDeferredImageDecode(duration); |
888 } | 752 } |
889 | 753 |
890 // static | 754 // static |
891 void TileManager::RunAnalyzeAndRasterTask( | 755 bool TileManager::RunAnalyzeAndRasterTask( |
892 const RasterWorkerPool::PictureTask::Callback& analyze_task, | 756 const base::Callback<void(PicturePileImpl*)>& analyze_task, |
893 const RasterWorkerPool::PictureTask::Callback& raster_task, | 757 const RasterWorkerPool::RasterTask::Callback& raster_task, |
758 SkDevice* device, | |
894 PicturePileImpl* picture_pile) { | 759 PicturePileImpl* picture_pile) { |
895 analyze_task.Run(picture_pile); | 760 analyze_task.Run(picture_pile); |
896 raster_task.Run(picture_pile); | 761 return raster_task.Run(device, picture_pile); |
897 } | 762 } |
898 | 763 |
899 // static | 764 // static |
900 void TileManager::RunAnalyzeTask( | 765 void TileManager::RunAnalyzeTask( |
901 PicturePileImpl::Analysis* analysis, | 766 PicturePileImpl::Analysis* analysis, |
902 gfx::Rect rect, | 767 gfx::Rect rect, |
903 float contents_scale, | 768 float contents_scale, |
904 bool use_color_estimator, | 769 bool use_color_estimator, |
905 const RasterTaskMetadata& metadata, | 770 const RasterTaskMetadata& metadata, |
906 RenderingStatsInstrumentation* stats_instrumentation, | 771 RenderingStatsInstrumentation* stats_instrumentation, |
(...skipping 22 matching lines...) Expand all Loading... | |
929 scoped_ptr<base::DictionaryValue> res(new base::DictionaryValue()); | 794 scoped_ptr<base::DictionaryValue> res(new base::DictionaryValue()); |
930 res->Set("tile_id", TracedValue::CreateIDRef(tile_id).release()); | 795 res->Set("tile_id", TracedValue::CreateIDRef(tile_id).release()); |
931 res->SetBoolean("is_tile_in_pending_tree_now_bin", | 796 res->SetBoolean("is_tile_in_pending_tree_now_bin", |
932 is_tile_in_pending_tree_now_bin); | 797 is_tile_in_pending_tree_now_bin); |
933 res->Set("resolution", TileResolutionAsValue(tile_resolution).release()); | 798 res->Set("resolution", TileResolutionAsValue(tile_resolution).release()); |
934 res->SetInteger("source_frame_number", source_frame_number); | 799 res->SetInteger("source_frame_number", source_frame_number); |
935 return res.PassAs<base::Value>(); | 800 return res.PassAs<base::Value>(); |
936 } | 801 } |
937 | 802 |
938 // static | 803 // static |
939 void TileManager::RunRasterTask( | 804 bool TileManager::RunRasterTask( |
940 uint8* buffer, | |
941 PicturePileImpl::Analysis* analysis, | 805 PicturePileImpl::Analysis* analysis, |
942 gfx::Rect rect, | 806 gfx::Rect rect, |
943 float contents_scale, | 807 float contents_scale, |
944 const RasterTaskMetadata& metadata, | 808 const RasterTaskMetadata& metadata, |
945 RenderingStatsInstrumentation* stats_instrumentation, | 809 RenderingStatsInstrumentation* stats_instrumentation, |
810 SkDevice* device, | |
946 PicturePileImpl* picture_pile) { | 811 PicturePileImpl* picture_pile) { |
947 TRACE_EVENT1( | 812 TRACE_EVENT1( |
948 "cc", "TileManager::RunRasterTask", | 813 "cc", "TileManager::RunRasterTask", |
949 "metadata", TracedValue::FromValue(metadata.AsValue().release())); | 814 "metadata", TracedValue::FromValue(metadata.AsValue().release())); |
950 devtools_instrumentation::ScopedLayerTask raster_task( | 815 devtools_instrumentation::ScopedLayerTask raster_task( |
951 devtools_instrumentation::kRasterTask, metadata.layer_id); | 816 devtools_instrumentation::kRasterTask, metadata.layer_id); |
952 | 817 |
953 DCHECK(picture_pile); | 818 DCHECK(picture_pile); |
954 DCHECK(analysis); | 819 DCHECK(analysis); |
955 | 820 DCHECK(device); |
956 // |buffer| can be NULL in lost context situations. | |
957 if (!buffer) | |
958 return; | |
959 | 821 |
960 if (analysis->is_solid_color) | 822 if (analysis->is_solid_color) |
961 return; | 823 return false; |
962 | 824 |
963 SkBitmap bitmap; | 825 SkCanvas canvas(device); |
964 bitmap.setConfig(SkBitmap::kARGB_8888_Config, rect.width(), rect.height()); | |
965 bitmap.setPixels(buffer); | |
966 SkDevice device(bitmap); | |
967 SkCanvas canvas(&device); | |
968 | 826 |
969 if (stats_instrumentation->record_rendering_stats()) { | 827 if (stats_instrumentation->record_rendering_stats()) { |
970 PicturePileImpl::RasterStats raster_stats; | 828 PicturePileImpl::RasterStats raster_stats; |
971 picture_pile->RasterToBitmap(&canvas, rect, contents_scale, &raster_stats); | 829 picture_pile->RasterToBitmap(&canvas, rect, contents_scale, &raster_stats); |
972 stats_instrumentation->AddRaster( | 830 stats_instrumentation->AddRaster( |
973 raster_stats.total_rasterize_time, | 831 raster_stats.total_rasterize_time, |
974 raster_stats.best_rasterize_time, | 832 raster_stats.best_rasterize_time, |
975 raster_stats.total_pixels_rasterized, | 833 raster_stats.total_pixels_rasterized, |
976 metadata.is_tile_in_pending_tree_now_bin); | 834 metadata.is_tile_in_pending_tree_now_bin); |
977 | 835 |
978 HISTOGRAM_CUSTOM_COUNTS( | 836 HISTOGRAM_CUSTOM_COUNTS( |
979 "Renderer4.PictureRasterTimeUS", | 837 "Renderer4.PictureRasterTimeUS", |
980 raster_stats.total_rasterize_time.InMicroseconds(), | 838 raster_stats.total_rasterize_time.InMicroseconds(), |
981 0, | 839 0, |
982 100000, | 840 100000, |
983 100); | 841 100); |
984 } else { | 842 } else { |
985 picture_pile->RasterToBitmap(&canvas, rect, contents_scale, NULL); | 843 picture_pile->RasterToBitmap(&canvas, rect, contents_scale, NULL); |
986 } | 844 } |
845 | |
846 return true; | |
987 } | 847 } |
988 | 848 |
989 } // namespace cc | 849 } // namespace cc |
OLD | NEW |