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
3 // found in the LICENSE file.
5 #include "cc/tile_manager.h"
10 #include "base/bind.h"
11 #include "base/command_line.h"
12 #include "base/debug/trace_event.h"
13 #include "base/logging.h"
14 #include "base/stringprintf.h"
15 #include "base/threading/thread.h"
16 #include "cc/platform_color.h"
17 #include "cc/rendering_stats.h"
18 #include "cc/resource_pool.h"
19 #include "cc/switches.h"
21 #include "third_party/skia/include/core/SkDevice.h"
25 const char* kRasterThreadNamePrefix
= "CompositorRaster";
27 const int kMaxRasterThreads
= 64;
28 const int kDefaultNumberOfRasterThreads
= 1;
30 // Allow two pending raster tasks per thread. This keeps resource usage
31 // low while making sure raster threads aren't unnecessarily idle.
32 const int kNumPendingRasterTasksPerThread
= 2;
34 // Determine bin based on three categories of tiles: things we need now,
35 // things we need soon, and eventually.
36 cc::TileManagerBin
BinFromTilePriority(const cc::TilePriority
& prio
) {
38 // The amount of time for which we want to have prepainting coverage.
39 const double prepainting_window_time_seconds
= 1.0;
40 const double backfling_guard_distance_pixels
= 314.0;
42 if (prio
.time_to_needed_in_seconds() == std::numeric_limits
<float>::max())
45 if (prio
.resolution
== cc::NON_IDEAL_RESOLUTION
)
46 return cc::EVENTUALLY_BIN
;
48 if (prio
.time_to_needed_in_seconds() == 0 ||
49 prio
.distance_to_visible_in_pixels
< backfling_guard_distance_pixels
)
52 if (prio
.time_to_needed_in_seconds() < prepainting_window_time_seconds
)
55 return cc::EVENTUALLY_BIN
;
62 class RasterThread
: public base::Thread
{
64 RasterThread(const std::string name
)
65 : base::Thread(name
.c_str()),
66 num_pending_tasks_(0) {
69 virtual ~RasterThread() {
73 int num_pending_tasks() { return num_pending_tasks_
; }
75 void PostRasterTaskAndReply(const tracked_objects::Location
& from_here
,
76 PicturePileImpl
* picture_pile
,
77 uint8_t* mapped_buffer
,
78 const gfx::Rect
& rect
,
80 RenderingStats
* stats
,
81 const base::Closure
& reply
) {
83 message_loop_proxy()->PostTaskAndReply(
85 base::Bind(&RunRasterTask
,
86 base::Unretained(picture_pile
),
91 base::Bind(&RasterThread::RunReply
, base::Unretained(this), reply
));
94 void PostImageDecodingTaskAndReply(const tracked_objects::Location
& from_here
,
95 skia::LazyPixelRef
* pixel_ref
,
96 RenderingStats
* stats
,
97 const base::Closure
& reply
) {
99 message_loop_proxy()->PostTaskAndReply(
101 base::Bind(&RunImageDecodeTask
, pixel_ref
, stats
),
102 base::Bind(&RasterThread::RunReply
, base::Unretained(this), reply
));
106 static void RunRasterTask(PicturePileImpl
* picture_pile
,
107 uint8_t* mapped_buffer
,
108 const gfx::Rect
& rect
,
109 float contents_scale
,
110 RenderingStats
* stats
) {
111 TRACE_EVENT0("cc", "RasterThread::RunRasterTask");
112 DCHECK(picture_pile
);
113 DCHECK(mapped_buffer
);
115 bitmap
.setConfig(SkBitmap::kARGB_8888_Config
, rect
.width(), rect
.height());
116 bitmap
.setPixels(mapped_buffer
);
117 SkDevice
device(bitmap
);
118 SkCanvas
canvas(&device
);
119 picture_pile
->Raster(
126 static void RunImageDecodeTask(skia::LazyPixelRef
* pixel_ref
,
127 RenderingStats
* stats
) {
128 TRACE_EVENT0("cc", "RasterThread::RunImageDecodeTask");
129 base::TimeTicks decodeBeginTime
= base::TimeTicks::Now();
131 stats
->totalDeferredImageDecodeTimeInSeconds
+=
132 (base::TimeTicks::Now() - decodeBeginTime
).InSecondsF();
135 void RunReply(const base::Closure
& reply
) {
136 --num_pending_tasks_
;
140 int num_pending_tasks_
;
142 DISALLOW_COPY_AND_ASSIGN(RasterThread
);
145 ManagedTileState::ManagedTileState()
146 : can_use_gpu_memory(false),
148 resource_is_being_initialized(false),
149 contents_swizzled(false),
150 need_to_gather_pixel_refs(true) {
153 ManagedTileState::~ManagedTileState() {
155 DCHECK(!resource_is_being_initialized
);
158 TileManager::TileManager(
159 TileManagerClient
* client
,
160 ResourceProvider
* resource_provider
,
161 size_t num_raster_threads
)
163 resource_pool_(ResourcePool::Create(resource_provider
)),
164 manage_tiles_pending_(false),
165 manage_tiles_call_count_(0),
166 check_for_completed_set_pixels_pending_(false) {
167 // Initialize all threads.
168 const std::string thread_name_prefix
= kRasterThreadNamePrefix
;
169 while (raster_threads_
.size() < num_raster_threads
) {
170 int thread_number
= raster_threads_
.size() + 1;
171 scoped_ptr
<RasterThread
> thread
= make_scoped_ptr(
172 new RasterThread(thread_name_prefix
+
173 StringPrintf("Worker%d", thread_number
).c_str()));
174 raster_threads_
.append(thread
.Pass());
180 TileManager::~TileManager() {
181 // Reset global state and manage. This should cause
182 // our memory usage to drop to zero.
183 global_state_
= GlobalStateThatImpactsTilePriority();
184 AssignGpuMemoryToTiles();
185 // This should finish all pending raster tasks and release any
186 // uninitialized resources.
187 raster_threads_
.clear();
189 DCHECK(tiles_
.size() == 0);
192 void TileManager::SetGlobalState(const GlobalStateThatImpactsTilePriority
& global_state
) {
193 global_state_
= global_state
;
194 resource_pool_
->SetMaxMemoryUsageBytes(global_state_
.memory_limit_in_bytes
);
195 ScheduleManageTiles();
198 void TileManager::RegisterTile(Tile
* tile
) {
199 tiles_
.push_back(tile
);
200 ScheduleManageTiles();
203 void TileManager::UnregisterTile(Tile
* tile
) {
204 for (TileList::iterator it
= tiles_with_image_decoding_tasks_
.begin();
205 it
!= tiles_with_image_decoding_tasks_
.end(); it
++) {
207 tiles_with_image_decoding_tasks_
.erase(it
);
211 for (TileVector::iterator it
= tiles_that_need_to_be_rasterized_
.begin();
212 it
!= tiles_that_need_to_be_rasterized_
.end(); it
++) {
214 tiles_that_need_to_be_rasterized_
.erase(it
);
218 for (TileVector::iterator it
= tiles_
.begin(); it
!= tiles_
.end(); it
++) {
220 FreeResourcesForTile(tile
);
225 DCHECK(false) << "Could not find tile version.";
228 void TileManager::WillModifyTilePriority(Tile
*, WhichTree tree
, const TilePriority
& new_priority
) {
229 // TODO(nduca): Do something smarter if reprioritization turns out to be
231 ScheduleManageTiles();
234 void TileManager::ScheduleManageTiles() {
235 if (manage_tiles_pending_
)
237 client_
->ScheduleManageTiles();
238 manage_tiles_pending_
= true;
241 void TileManager::ScheduleCheckForCompletedSetPixels() {
242 if (check_for_completed_set_pixels_pending_
)
244 client_
->ScheduleCheckForCompletedSetPixels();
245 check_for_completed_set_pixels_pending_
= true;
248 class BinComparator
{
250 bool operator() (const Tile
* a
, const Tile
* b
) const {
251 const ManagedTileState
& ams
= a
->managed_state();
252 const ManagedTileState
& bms
= b
->managed_state();
253 if (ams
.raster_bin
!= bms
.raster_bin
)
254 return ams
.raster_bin
< bms
.raster_bin
;
256 if (ams
.resolution
!= bms
.resolution
)
257 return ams
.resolution
< ams
.resolution
;
260 ams
.time_to_needed_in_seconds
<
261 bms
.time_to_needed_in_seconds
;
265 void TileManager::ManageTiles() {
266 TRACE_EVENT0("cc", "TileManager::ManageTiles");
267 manage_tiles_pending_
= false;
268 ++manage_tiles_call_count_
;
270 const bool smoothness_takes_priority
=
271 global_state_
.smoothness_takes_priority
;
273 // For each tree, bin into different categories of tiles.
274 for (TileVector::iterator it
= tiles_
.begin(); it
!= tiles_
.end(); ++it
) {
276 ManagedTileState
& mts
= tile
->managed_state();
277 mts
.bin
[ACTIVE_TREE
] = BinFromTilePriority(tile
->priority(ACTIVE_TREE
));
278 mts
.bin
[PENDING_TREE
] = BinFromTilePriority(tile
->priority(PENDING_TREE
));
281 if (smoothness_takes_priority
)
282 prio
= tile
->priority(ACTIVE_TREE
);
284 prio
= tile
->combined_priority();
286 mts
.resolution
= prio
.resolution
;
287 mts
.time_to_needed_in_seconds
= prio
.time_to_needed_in_seconds();
288 mts
.raster_bin
= BinFromTilePriority(prio
);
291 // Memory limit policy works by mapping some bin states to the NEVER bin.
292 TileManagerBin bin_map
[NUM_BINS
];
293 if (global_state_
.memory_limit_policy
== ALLOW_NOTHING
) {
294 bin_map
[NOW_BIN
] = NEVER_BIN
;
295 bin_map
[SOON_BIN
] = NEVER_BIN
;
296 bin_map
[EVENTUALLY_BIN
] = NEVER_BIN
;
297 bin_map
[NEVER_BIN
] = NEVER_BIN
;
298 } else if (global_state_
.memory_limit_policy
== ALLOW_ABSOLUTE_MINIMUM
) {
299 bin_map
[NOW_BIN
] = NOW_BIN
;
300 bin_map
[SOON_BIN
] = NEVER_BIN
;
301 bin_map
[EVENTUALLY_BIN
] = NEVER_BIN
;
302 bin_map
[NEVER_BIN
] = NEVER_BIN
;
303 } else if (global_state_
.memory_limit_policy
== ALLOW_PREPAINT_ONLY
) {
304 bin_map
[NOW_BIN
] = NOW_BIN
;
305 bin_map
[SOON_BIN
] = SOON_BIN
;
306 bin_map
[EVENTUALLY_BIN
] = NEVER_BIN
;
307 bin_map
[NEVER_BIN
] = NEVER_BIN
;
309 bin_map
[NOW_BIN
] = NOW_BIN
;
310 bin_map
[SOON_BIN
] = SOON_BIN
;
311 bin_map
[EVENTUALLY_BIN
] = EVENTUALLY_BIN
;
312 bin_map
[NEVER_BIN
] = NEVER_BIN
;
314 for (TileVector::iterator it
= tiles_
.begin(); it
!= tiles_
.end(); ++it
) {
316 ManagedTileState
& mts
= tile
->managed_state();
317 mts
.bin
[ACTIVE_TREE
] = bin_map
[mts
.bin
[ACTIVE_TREE
]];
318 mts
.bin
[PENDING_TREE
] = bin_map
[mts
.bin
[PENDING_TREE
]];
319 mts
.raster_bin
= bin_map
[mts
.raster_bin
];
322 // Update bin counts.
324 for (TileVector::iterator it
= tiles_
.begin(); it
!= tiles_
.end(); ++it
) {
326 ManagedTileState
& mts
= tile
->managed_state();
327 for (int i
= 0; i
< NUM_TREES
; ++i
)
328 tiles_in_bin_count_
[mts
.bin
[i
]][i
]++;
330 // Increment drawable count if GetResourceId() doesn't return 0.
331 if (tile
->GetResourceId()) {
332 for (int i
= 0; i
< NUM_TREES
; ++i
)
333 drawable_tiles_in_bin_count_
[mts
.bin
[i
]][i
]++;
338 std::sort(tiles_
.begin(), tiles_
.end(), BinComparator());
340 // Assign gpu memory and determine what tiles need to be rasterized.
341 AssignGpuMemoryToTiles();
343 // Finally, kick the rasterizer.
347 void TileManager::CheckForCompletedSetPixels() {
348 check_for_completed_set_pixels_pending_
= false;
350 while (!tiles_with_pending_set_pixels_
.empty()) {
351 Tile
* tile
= tiles_with_pending_set_pixels_
.front();
352 DCHECK(tile
->managed_state().resource
);
354 // Set pixel tasks complete in the order they are posted.
355 if (!resource_pool_
->resource_provider()->didSetPixelsComplete(
356 tile
->managed_state().resource
->id())) {
357 ScheduleCheckForCompletedSetPixels();
361 // It's now safe to release the pixel buffer.
362 resource_pool_
->resource_provider()->releasePixelBuffer(
363 tile
->managed_state().resource
->id());
365 DidFinishTileInitialization(tile
);
366 tiles_with_pending_set_pixels_
.pop();
370 void TileManager::GetRenderingStats(RenderingStats
* stats
) {
371 stats
->totalRasterizeTimeInSeconds
=
372 rendering_stats_
.totalRasterizeTimeInSeconds
;
373 stats
->totalPixelsRasterized
= rendering_stats_
.totalPixelsRasterized
;
374 stats
->totalDeferredImageDecodeCount
=
375 rendering_stats_
.totalDeferredImageDecodeCount
;
376 stats
->totalDeferredImageCacheHitCount
=
377 rendering_stats_
.totalDeferredImageCacheHitCount
;
378 stats
->totalImageGatheringCount
= rendering_stats_
.totalImageGatheringCount
;
379 stats
->totalDeferredImageDecodeTimeInSeconds
=
380 rendering_stats_
.totalDeferredImageDecodeTimeInSeconds
;
381 stats
->totalImageGatheringTimeInSeconds
=
382 rendering_stats_
.totalImageGatheringTimeInSeconds
;
385 int TileManager::GetTilesInBinCount(TileManagerBin bin
, WhichTree tree
) {
387 DCHECK(bin
< NUM_BINS
);
389 DCHECK(tree
< NUM_TREES
);
390 return tiles_in_bin_count_
[bin
][tree
];
393 int TileManager::GetDrawableTilesInBinCount(
394 TileManagerBin bin
, WhichTree tree
) {
396 DCHECK(bin
< NUM_BINS
);
398 DCHECK(tree
< NUM_TREES
);
399 return drawable_tiles_in_bin_count_
[bin
][tree
];
402 void TileManager::ResetBinCounts() {
403 for (int i
= 0; i
< NUM_BINS
; ++i
)
404 for (int j
= 0; j
< NUM_TREES
; ++j
)
405 tiles_in_bin_count_
[i
][j
] = drawable_tiles_in_bin_count_
[i
][j
] = 0;
408 void TileManager::AssignGpuMemoryToTiles() {
409 TRACE_EVENT0("cc", "TileManager::AssignGpuMemoryToTiles");
410 // Some memory cannot be released. Figure out which.
411 size_t unreleasable_bytes
= 0;
412 for (TileVector::iterator it
= tiles_
.begin(); it
!= tiles_
.end(); ++it
) {
414 if (!tile
->managed_state().can_be_freed
)
415 unreleasable_bytes
+= tile
->bytes_consumed_if_allocated();
418 // Now give memory out to the tiles until we're out, and build
419 // the needs-to-be-rasterized queue.
420 tiles_that_need_to_be_rasterized_
.erase(
421 tiles_that_need_to_be_rasterized_
.begin(),
422 tiles_that_need_to_be_rasterized_
.end());
424 // Reset the image decoding list so that we don't mess up with tile
425 // priorities. Tiles will be added to the image decoding list again
426 // when DispatchMoreTasks() is called.
427 tiles_with_image_decoding_tasks_
.clear();
429 size_t bytes_left
= global_state_
.memory_limit_in_bytes
- unreleasable_bytes
;
430 for (TileVector::iterator it
= tiles_
.begin(); it
!= tiles_
.end(); ++it
) {
432 size_t tile_bytes
= tile
->bytes_consumed_if_allocated();
433 ManagedTileState
& managed_tile_state
= tile
->managed_state();
434 if (!managed_tile_state
.can_be_freed
)
436 if (managed_tile_state
.raster_bin
== NEVER_BIN
) {
437 managed_tile_state
.can_use_gpu_memory
= false;
438 FreeResourcesForTile(tile
);
441 if (tile_bytes
> bytes_left
) {
442 managed_tile_state
.can_use_gpu_memory
= false;
443 FreeResourcesForTile(tile
);
446 bytes_left
-= tile_bytes
;
447 managed_tile_state
.can_use_gpu_memory
= true;
448 if (!managed_tile_state
.resource
&&
449 !managed_tile_state
.resource_is_being_initialized
)
450 tiles_that_need_to_be_rasterized_
.push_back(tile
);
453 // Reverse two tiles_that_need_* vectors such that pop_back gets
454 // the highest priority tile.
456 tiles_that_need_to_be_rasterized_
.begin(),
457 tiles_that_need_to_be_rasterized_
.end());
460 void TileManager::FreeResourcesForTile(Tile
* tile
) {
461 ManagedTileState
& managed_tile_state
= tile
->managed_state();
462 DCHECK(managed_tile_state
.can_be_freed
);
463 if (managed_tile_state
.resource
)
464 resource_pool_
->ReleaseResource(managed_tile_state
.resource
.Pass());
467 RasterThread
* TileManager::GetFreeRasterThread() {
468 RasterThread
* thread
= 0;
469 for (RasterThreadVector::iterator it
= raster_threads_
.begin();
470 it
!= raster_threads_
.end(); ++it
) {
471 if ((*it
)->num_pending_tasks() == kNumPendingRasterTasksPerThread
)
473 // Check if this is the best thread we've found so far.
474 if (!thread
|| (*it
)->num_pending_tasks() < thread
->num_pending_tasks())
480 void TileManager::DispatchMoreTasks() {
481 // Because tiles in the image decoding list have higher priorities, we
482 // need to process those tiles first before we start to handle the tiles
483 // in the need_to_be_rasterized queue.
484 std::list
<Tile
*>::iterator it
= tiles_with_image_decoding_tasks_
.begin();
485 while (it
!= tiles_with_image_decoding_tasks_
.end()) {
486 DispatchImageDecodingTasksForTile(*it
);
487 ManagedTileState
& managed_state
= (*it
)->managed_state();
488 if (managed_state
.pending_pixel_refs
.empty()) {
489 RasterThread
* thread
= GetFreeRasterThread();
492 DispatchOneRasterTask(thread
, *it
);
493 tiles_with_image_decoding_tasks_
.erase(it
++);
499 // Process all tiles in the need_to_be_rasterized queue. If a tile has
500 // image decoding tasks, put it to the back of the image decoding list.
501 while (!tiles_that_need_to_be_rasterized_
.empty()) {
502 Tile
* tile
= tiles_that_need_to_be_rasterized_
.back();
503 DispatchImageDecodingTasksForTile(tile
);
504 ManagedTileState
& managed_state
= tile
->managed_state();
505 if (!managed_state
.pending_pixel_refs
.empty()) {
506 tiles_with_image_decoding_tasks_
.push_back(tile
);
508 RasterThread
* thread
= GetFreeRasterThread();
511 DispatchOneRasterTask(thread
, tile
);
513 tiles_that_need_to_be_rasterized_
.pop_back();
517 void TileManager::GatherPixelRefsForTile(Tile
* tile
) {
518 TRACE_EVENT0("cc", "TileManager::GatherPixelRefsForTile");
519 ManagedTileState
& managed_state
= tile
->managed_state();
520 if (managed_state
.need_to_gather_pixel_refs
) {
521 base::TimeTicks gather_begin_time
= base::TimeTicks::Now();
522 const_cast<PicturePileImpl
*>(tile
->picture_pile())->GatherPixelRefs(
523 tile
->content_rect_
, managed_state
.pending_pixel_refs
);
524 rendering_stats_
.totalImageGatheringCount
++;
525 rendering_stats_
.totalImageGatheringTimeInSeconds
+=
526 (base::TimeTicks::Now() - gather_begin_time
).InSecondsF();
527 managed_state
.need_to_gather_pixel_refs
= false;
531 void TileManager::DispatchImageDecodingTasksForTile(Tile
* tile
) {
532 GatherPixelRefsForTile(tile
);
533 std::list
<skia::LazyPixelRef
*>& pending_pixel_refs
=
534 tile
->managed_state().pending_pixel_refs
;
535 std::list
<skia::LazyPixelRef
*>::iterator it
= pending_pixel_refs
.begin();
536 while (it
!= pending_pixel_refs
.end()) {
537 if (pending_decode_tasks_
.end() != pending_decode_tasks_
.find(
538 (*it
)->getGenerationID())) {
542 // TODO(qinmin): passing correct image size to PrepareToDecode().
543 if ((*it
)->PrepareToDecode(skia::LazyPixelRef::PrepareParams())) {
544 rendering_stats_
.totalDeferredImageCacheHitCount
++;
545 pending_pixel_refs
.erase(it
++);
547 RasterThread
* thread
= GetFreeRasterThread();
550 DispatchOneImageDecodingTask(thread
, tile
, *it
);
556 void TileManager::DispatchOneImageDecodingTask(RasterThread
* thread
,
557 scoped_refptr
<Tile
> tile
,
558 skia::LazyPixelRef
* pixel_ref
) {
559 TRACE_EVENT0("cc", "TileManager::DispatchOneImageDecodingTask");
560 uint32_t pixel_ref_id
= pixel_ref
->getGenerationID();
561 DCHECK(pending_decode_tasks_
.end() ==
562 pending_decode_tasks_
.find(pixel_ref_id
));
563 pending_decode_tasks_
[pixel_ref_id
] = pixel_ref
;
564 RenderingStats
* stats
= new RenderingStats();
566 thread
->PostImageDecodingTaskAndReply(
570 base::Bind(&TileManager::OnImageDecodingTaskCompleted
,
571 base::Unretained(this),
577 void TileManager::OnImageDecodingTaskCompleted(scoped_refptr
<Tile
> tile
,
578 uint32_t pixel_ref_id
,
579 RenderingStats
* stats
) {
580 TRACE_EVENT0("cc", "TileManager::OnImageDecoded");
581 pending_decode_tasks_
.erase(pixel_ref_id
);
582 rendering_stats_
.totalDeferredImageDecodeTimeInSeconds
+=
583 stats
->totalDeferredImageDecodeTimeInSeconds
;
584 rendering_stats_
.totalDeferredImageDecodeCount
++;
586 for (TileList::iterator it
= tiles_with_image_decoding_tasks_
.begin();
587 it
!= tiles_with_image_decoding_tasks_
.end(); ++it
) {
588 std::list
<skia::LazyPixelRef
*>& pixel_refs
=
589 (*it
)->managed_state().pending_pixel_refs
;
590 for (std::list
<skia::LazyPixelRef
*>::iterator pixel_it
=
591 pixel_refs
.begin(); pixel_it
!= pixel_refs
.end(); ++pixel_it
) {
592 if (pixel_ref_id
== (*pixel_it
)->getGenerationID()) {
593 pixel_refs
.erase(pixel_it
);
601 void TileManager::DispatchOneRasterTask(
602 RasterThread
* thread
, scoped_refptr
<Tile
> tile
) {
603 TRACE_EVENT0("cc", "TileManager::DispatchOneRasterTask");
604 ManagedTileState
& managed_tile_state
= tile
->managed_state();
605 DCHECK(managed_tile_state
.can_use_gpu_memory
);
606 scoped_ptr
<ResourcePool::Resource
> resource
=
607 resource_pool_
->AcquireResource(tile
->tile_size_
.size(), tile
->format_
);
608 resource_pool_
->resource_provider()->acquirePixelBuffer(resource
->id());
610 managed_tile_state
.resource_is_being_initialized
= true;
611 managed_tile_state
.can_be_freed
= false;
613 ResourceProvider::ResourceId resource_id
= resource
->id();
614 scoped_refptr
<PicturePileImpl
> picture_pile_clone
=
615 tile
->picture_pile()->GetCloneForDrawingOnThread(thread
);
616 RenderingStats
* stats
= new RenderingStats();
618 thread
->PostRasterTaskAndReply(
620 picture_pile_clone
.get(),
621 resource_pool_
->resource_provider()->mapPixelBuffer(resource_id
),
623 tile
->contents_scale(),
625 base::Bind(&TileManager::OnRasterTaskCompleted
,
626 base::Unretained(this),
628 base::Passed(&resource
),
630 manage_tiles_call_count_
,
634 void TileManager::OnRasterTaskCompleted(
635 scoped_refptr
<Tile
> tile
,
636 scoped_ptr
<ResourcePool::Resource
> resource
,
637 scoped_refptr
<PicturePileImpl
> picture_pile_clone
,
638 int manage_tiles_call_count_when_dispatched
,
639 RenderingStats
* stats
) {
640 TRACE_EVENT0("cc", "TileManager::OnRasterTaskCompleted");
641 rendering_stats_
.totalRasterizeTimeInSeconds
+=
642 stats
->totalRasterizeTimeInSeconds
;
643 rendering_stats_
.totalPixelsRasterized
+= stats
->totalPixelsRasterized
;
646 // Release raster resources.
647 resource_pool_
->resource_provider()->unmapPixelBuffer(resource
->id());
649 ManagedTileState
& managed_tile_state
= tile
->managed_state();
650 managed_tile_state
.can_be_freed
= true;
652 // Tile can be freed after the completion of the raster task. Call
653 // AssignGpuMemoryToTiles() to re-assign gpu memory to highest priority
654 // tiles if ManageTiles() was called since task was dispatched. The result
655 // of this could be that this tile is no longer allowed to use gpu
656 // memory and in that case we need to abort initialization and free all
657 // associated resources before calling DispatchMoreTasks().
658 if (manage_tiles_call_count_when_dispatched
!= manage_tiles_call_count_
)
659 AssignGpuMemoryToTiles();
661 // Finish resource initialization if |can_use_gpu_memory| is true.
662 if (managed_tile_state
.can_use_gpu_memory
) {
663 // The component order may be bgra if we're uploading bgra pixels to rgba
664 // texture. Mark contents as swizzled if image component order is
665 // different than texture format.
666 managed_tile_state
.contents_swizzled
=
667 !PlatformColor::sameComponentOrder(tile
->format_
);
669 // Tile resources can't be freed until upload has completed.
670 managed_tile_state
.can_be_freed
= false;
672 resource_pool_
->resource_provider()->beginSetPixels(resource
->id());
673 managed_tile_state
.resource
= resource
.Pass();
674 tiles_with_pending_set_pixels_
.push(tile
);
676 ScheduleCheckForCompletedSetPixels();
678 resource_pool_
->resource_provider()->releasePixelBuffer(resource
->id());
679 resource_pool_
->ReleaseResource(resource
.Pass());
680 managed_tile_state
.resource_is_being_initialized
= false;
685 void TileManager::DidFinishTileInitialization(Tile
* tile
) {
686 ManagedTileState
& managed_tile_state
= tile
->managed_state();
687 DCHECK(managed_tile_state
.resource
);
688 managed_tile_state
.resource_is_being_initialized
= false;
689 managed_tile_state
.can_be_freed
= true;
690 for (int i
= 0; i
< NUM_TREES
; ++i
)
691 drawable_tiles_in_bin_count_
[managed_tile_state
.bin
[i
]][i
]++;