Chromium Code Reviews| 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/picture_pile.h" | 5 #include "cc/resources/picture_pile.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> | 8 #include <limits> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 159 ContentLayerClient* painter, | 159 ContentLayerClient* painter, |
| 160 Region* invalidation, | 160 Region* invalidation, |
| 161 SkColor background_color, | 161 SkColor background_color, |
| 162 bool contents_opaque, | 162 bool contents_opaque, |
| 163 bool contents_fill_bounds_completely, | 163 bool contents_fill_bounds_completely, |
| 164 const gfx::Size& layer_size, | 164 const gfx::Size& layer_size, |
| 165 const gfx::Rect& visible_layer_rect, | 165 const gfx::Rect& visible_layer_rect, |
| 166 int frame_number, | 166 int frame_number, |
| 167 Picture::RecordingMode recording_mode, | 167 Picture::RecordingMode recording_mode, |
| 168 RenderingStatsInstrumentation* stats_instrumentation) { | 168 RenderingStatsInstrumentation* stats_instrumentation) { |
| 169 TRACE_EVENT0("cc", "PicturePile::UpdateAndExpandInvalidation"); | |
|
ajuma
2014/10/10 15:43:03
Did you mean to add these trace events, or is this
danakj
2014/10/10 16:07:15
Oh thanks that's from debugging the next bug, they
| |
| 169 background_color_ = background_color; | 170 background_color_ = background_color; |
| 170 contents_opaque_ = contents_opaque; | 171 contents_opaque_ = contents_opaque; |
| 171 contents_fill_bounds_completely_ = contents_fill_bounds_completely; | 172 contents_fill_bounds_completely_ = contents_fill_bounds_completely; |
| 172 | 173 |
| 173 bool updated = false; | 174 bool updated = false; |
| 174 | 175 |
| 175 Region resize_invalidation; | 176 Region resize_invalidation; |
| 176 gfx::Size old_tiling_size = tiling_size(); | 177 gfx::Size old_tiling_size = tiling_size(); |
| 177 if (old_tiling_size != layer_size) { | 178 if (old_tiling_size != layer_size) { |
| 178 tiling_.SetTilingSize(layer_size); | 179 tiling_.SetTilingSize(layer_size); |
| 179 updated = true; | 180 updated = true; |
| 180 } | 181 } |
| 181 | 182 |
| 182 gfx::Rect interest_rect = visible_layer_rect; | 183 gfx::Rect interest_rect = visible_layer_rect; |
| 183 interest_rect.Inset( | 184 interest_rect.Inset( |
| 184 -kPixelDistanceToRecord, | 185 -kPixelDistanceToRecord, |
| 185 -kPixelDistanceToRecord, | 186 -kPixelDistanceToRecord, |
| 186 -kPixelDistanceToRecord, | 187 -kPixelDistanceToRecord, |
| 187 -kPixelDistanceToRecord); | 188 -kPixelDistanceToRecord); |
| 188 recorded_viewport_ = interest_rect; | 189 recorded_viewport_ = interest_rect; |
| 189 recorded_viewport_.Intersect(gfx::Rect(tiling_size())); | 190 recorded_viewport_.Intersect(gfx::Rect(tiling_size())); |
| 190 | 191 |
| 191 gfx::Rect interest_rect_over_tiles = | 192 gfx::Rect interest_rect_over_tiles = |
| 192 tiling_.ExpandRectToTileBounds(interest_rect); | 193 tiling_.ExpandRectToTileBounds(interest_rect); |
| 193 | 194 |
| 194 if (old_tiling_size != layer_size) { | 195 if (old_tiling_size != layer_size) { |
| 196 TRACE_EVENT0("cc", "PicturePile::SizeChanged"); | |
| 195 has_any_recordings_ = false; | 197 has_any_recordings_ = false; |
| 196 | 198 |
| 197 // Drop recordings that are outside the new layer bounds or that changed | 199 // Drop recordings that are outside the new layer bounds or that changed |
| 198 // size. | 200 // size. |
| 199 std::vector<PictureMapKey> to_erase; | 201 std::vector<PictureMapKey> to_erase; |
| 200 int min_toss_x = tiling_.num_tiles_x(); | 202 int min_toss_x = tiling_.num_tiles_x(); |
| 201 if (tiling_size().width() > old_tiling_size.width()) { | 203 if (tiling_size().width() > old_tiling_size.width()) { |
| 202 min_toss_x = | 204 min_toss_x = |
| 203 tiling_.FirstBorderTileXIndexFromSrcCoord(old_tiling_size.width()); | 205 tiling_.FirstBorderTileXIndexFromSrcCoord(old_tiling_size.width()); |
| 204 } | 206 } |
| 205 int min_toss_y = tiling_.num_tiles_y(); | 207 int min_toss_y = tiling_.num_tiles_y(); |
| 206 if (tiling_size().height() > old_tiling_size.height()) { | 208 if (tiling_size().height() > old_tiling_size.height()) { |
| 207 min_toss_y = | 209 min_toss_y = |
| 208 tiling_.FirstBorderTileYIndexFromSrcCoord(old_tiling_size.height()); | 210 tiling_.FirstBorderTileYIndexFromSrcCoord(old_tiling_size.height()); |
| 209 } | 211 } |
| 212 { | |
| 213 TRACE_EVENT0("cc", "PicturePile::FindingKeys"); | |
| 210 for (PictureMap::const_iterator it = picture_map_.begin(); | 214 for (PictureMap::const_iterator it = picture_map_.begin(); |
| 211 it != picture_map_.end(); | 215 it != picture_map_.end(); |
| 212 ++it) { | 216 ++it) { |
| 213 const PictureMapKey& key = it->first; | 217 const PictureMapKey& key = it->first; |
| 214 if (key.first < min_toss_x && key.second < min_toss_y) { | 218 if (key.first < min_toss_x && key.second < min_toss_y) { |
| 215 has_any_recordings_ |= !!it->second.GetPicture(); | 219 has_any_recordings_ |= !!it->second.GetPicture(); |
| 216 continue; | 220 continue; |
| 217 } | 221 } |
| 218 to_erase.push_back(key); | 222 to_erase.push_back(key); |
| 219 } | 223 } |
| 224 } | |
| 220 | 225 |
| 226 { | |
| 227 TRACE_EVENT0("cc", "PicturePile::DeletingKeys"); | |
| 221 for (size_t i = 0; i < to_erase.size(); ++i) | 228 for (size_t i = 0; i < to_erase.size(); ++i) |
| 222 picture_map_.erase(to_erase[i]); | 229 picture_map_.erase(to_erase[i]); |
| 230 } | |
| 223 | 231 |
| 224 // If a recording is dropped and not re-recorded below, invalidate that | 232 // If a recording is dropped and not re-recorded below, invalidate that |
| 225 // full recording to cause any raster tiles that would use it to be | 233 // full recording to cause any raster tiles that would use it to be |
| 226 // dropped. | 234 // dropped. |
| 227 // If the recording will be replaced below, just invalidate newly exposed | 235 // If the recording will be replaced below, just invalidate newly exposed |
| 228 // areas to force raster tiles that include the old recording to know | 236 // areas to force raster tiles that include the old recording to know |
| 229 // there is new recording to display. | 237 // there is new recording to display. |
| 230 gfx::Rect old_tiling_rect_over_tiles = | 238 gfx::Rect old_tiling_rect_over_tiles = |
| 231 tiling_.ExpandRectToTileBounds(gfx::Rect(old_tiling_size)); | 239 tiling_.ExpandRectToTileBounds(gfx::Rect(old_tiling_size)); |
| 232 if (min_toss_x < tiling_.num_tiles_x()) { | 240 if (min_toss_x < tiling_.num_tiles_x()) { |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 374 resize_invalidation.Union(right_rect); | 382 resize_invalidation.Union(right_rect); |
| 375 resize_invalidation.Union(top_rect); | 383 resize_invalidation.Union(top_rect); |
| 376 resize_invalidation.Union(bottom_rect); | 384 resize_invalidation.Union(bottom_rect); |
| 377 resize_invalidation.Union(exposed_rect); | 385 resize_invalidation.Union(exposed_rect); |
| 378 } | 386 } |
| 379 } | 387 } |
| 380 | 388 |
| 381 Region invalidation_expanded_to_full_tiles; | 389 Region invalidation_expanded_to_full_tiles; |
| 382 for (Region::Iterator i(*invalidation); i.has_rect(); i.next()) { | 390 for (Region::Iterator i(*invalidation); i.has_rect(); i.next()) { |
| 383 gfx::Rect invalid_rect = i.rect(); | 391 gfx::Rect invalid_rect = i.rect(); |
| 392 TRACE_EVENT1( | |
| 393 "cc", "PicturePile::Invalidating", "rect", invalid_rect.ToString()); | |
| 384 | 394 |
| 385 // Expand invalidation that is outside tiles that intersect the interest | 395 // Expand invalidation that is outside tiles that intersect the interest |
| 386 // rect. These tiles are no longer valid and should be considerered fully | 396 // rect. These tiles are no longer valid and should be considerered fully |
| 387 // invalid, so we can know to not keep around raster tiles that intersect | 397 // invalid, so we can know to not keep around raster tiles that intersect |
| 388 // with these recording tiles. | 398 // with these recording tiles. |
| 389 gfx::Rect invalid_rect_outside_interest_rect_tiles = invalid_rect; | 399 gfx::Rect invalid_rect_outside_interest_rect_tiles = invalid_rect; |
| 390 // TODO(danakj): We should have a Rect-subtract-Rect-to-2-rects operator | 400 // TODO(danakj): We should have a Rect-subtract-Rect-to-2-rects operator |
| 391 // instead of using Rect::Subtract which gives you the bounding box of the | 401 // instead of using Rect::Subtract which gives you the bounding box of the |
| 392 // subtraction. | 402 // subtraction. |
| 393 invalid_rect_outside_interest_rect_tiles.Subtract(interest_rect_over_tiles); | 403 invalid_rect_outside_interest_rect_tiles.Subtract(interest_rect_over_tiles); |
| 394 invalidation_expanded_to_full_tiles.Union(tiling_.ExpandRectToTileBounds( | 404 invalidation_expanded_to_full_tiles.Union(tiling_.ExpandRectToTileBounds( |
| 395 invalid_rect_outside_interest_rect_tiles)); | 405 invalid_rect_outside_interest_rect_tiles)); |
| 396 | 406 |
| 397 // Split this inflated invalidation across tile boundaries and apply it | 407 // Split this inflated invalidation across tile boundaries and apply it |
| 398 // to all tiles that it touches. | 408 // to all tiles that it touches. |
| 399 bool include_borders = true; | 409 bool include_borders = true; |
| 410 int n = 0; | |
| 400 for (TilingData::Iterator iter(&tiling_, invalid_rect, include_borders); | 411 for (TilingData::Iterator iter(&tiling_, invalid_rect, include_borders); |
| 401 iter; | 412 iter; |
| 402 ++iter) { | 413 ++iter) { |
| 414 ++n; | |
| 403 const PictureMapKey& key = iter.index(); | 415 const PictureMapKey& key = iter.index(); |
| 404 | 416 |
| 405 PictureMap::iterator picture_it = picture_map_.find(key); | 417 PictureMap::iterator picture_it = picture_map_.find(key); |
| 406 if (picture_it == picture_map_.end()) | 418 if (picture_it == picture_map_.end()) |
| 407 continue; | 419 continue; |
| 408 | 420 |
| 409 // Inform the grid cell that it has been invalidated in this frame. | 421 // Inform the grid cell that it has been invalidated in this frame. |
| 410 updated = picture_it->second.Invalidate(frame_number) || updated; | 422 updated = picture_it->second.Invalidate(frame_number) || updated; |
| 411 // Invalidate drops the picture so the whole tile better be invalidated if | 423 // Invalidate drops the picture so the whole tile better be invalidated if |
| 412 // it won't be re-recorded below. | 424 // it won't be re-recorded below. |
| 413 DCHECK_IMPLIES(!tiling_.TileBounds(key.first, key.second) | 425 DCHECK_IMPLIES(!tiling_.TileBounds(key.first, key.second) |
| 414 .Intersects(interest_rect_over_tiles), | 426 .Intersects(interest_rect_over_tiles), |
| 415 invalidation_expanded_to_full_tiles.Contains( | 427 invalidation_expanded_to_full_tiles.Contains( |
| 416 tiling_.TileBounds(key.first, key.second))); | 428 tiling_.TileBounds(key.first, key.second))); |
| 417 } | 429 } |
| 430 TRACE_EVENT1("cc", "PicturePile::InvalidatingTiles", "tiles", n); | |
| 418 } | 431 } |
| 419 | 432 |
| 433 { | |
| 434 TRACE_EVENT0("cc", "PicturePile::Unioning"); | |
| 420 invalidation->Union(invalidation_expanded_to_full_tiles); | 435 invalidation->Union(invalidation_expanded_to_full_tiles); |
| 421 invalidation->Union(resize_invalidation); | 436 invalidation->Union(resize_invalidation); |
| 437 } | |
| 422 | 438 |
| 423 // Make a list of all invalid tiles; we will attempt to | 439 // Make a list of all invalid tiles; we will attempt to |
| 424 // cluster these into multiple invalidation regions. | 440 // cluster these into multiple invalidation regions. |
| 425 std::vector<gfx::Rect> invalid_tiles; | 441 std::vector<gfx::Rect> invalid_tiles; |
| 426 bool include_borders = true; | 442 bool include_borders = true; |
| 427 for (TilingData::Iterator it(&tiling_, interest_rect, include_borders); it; | 443 for (TilingData::Iterator it(&tiling_, interest_rect, include_borders); it; |
| 428 ++it) { | 444 ++it) { |
| 445 TRACE_EVENT0("cc", "PicturePile::ListingTiles"); | |
| 429 const PictureMapKey& key = it.index(); | 446 const PictureMapKey& key = it.index(); |
| 430 PictureInfo& info = picture_map_[key]; | 447 PictureInfo& info = picture_map_[key]; |
| 431 | 448 |
| 432 gfx::Rect rect = PaddedRect(key); | 449 gfx::Rect rect = PaddedRect(key); |
| 433 int distance_to_visible = | 450 int distance_to_visible = |
| 434 rect.ManhattanInternalDistance(visible_layer_rect); | 451 rect.ManhattanInternalDistance(visible_layer_rect); |
| 435 | 452 |
| 436 if (info.NeedsRecording(frame_number, distance_to_visible)) { | 453 if (info.NeedsRecording(frame_number, distance_to_visible)) { |
| 437 gfx::Rect tile = tiling_.TileBounds(key.first, key.second); | 454 gfx::Rect tile = tiling_.TileBounds(key.first, key.second); |
| 438 invalid_tiles.push_back(tile); | 455 invalid_tiles.push_back(tile); |
| 439 } else if (!info.GetPicture()) { | 456 } else if (!info.GetPicture()) { |
| 440 if (recorded_viewport_.Intersects(rect)) { | 457 if (recorded_viewport_.Intersects(rect)) { |
| 441 // Recorded viewport is just an optimization for a fully recorded | 458 // Recorded viewport is just an optimization for a fully recorded |
| 442 // interest rect. In this case, a tile in that rect has declined | 459 // interest rect. In this case, a tile in that rect has declined |
| 443 // to be recorded (probably due to frequent invalidations). | 460 // to be recorded (probably due to frequent invalidations). |
| 444 // TODO(enne): Shrink the recorded_viewport_ rather than clearing. | 461 // TODO(enne): Shrink the recorded_viewport_ rather than clearing. |
| 445 recorded_viewport_ = gfx::Rect(); | 462 recorded_viewport_ = gfx::Rect(); |
| 446 } | 463 } |
| 447 | 464 |
| 448 // If a tile in the interest rect is not recorded, the entire tile needs | 465 // If a tile in the interest rect is not recorded, the entire tile needs |
| 449 // to be considered invalid, so that we know not to keep around raster | 466 // to be considered invalid, so that we know not to keep around raster |
| 450 // tiles that intersect this recording tile. | 467 // tiles that intersect this recording tile. |
| 451 invalidation->Union(tiling_.TileBounds(it.index_x(), it.index_y())); | 468 invalidation->Union(tiling_.TileBounds(it.index_x(), it.index_y())); |
| 452 } | 469 } |
| 453 } | 470 } |
| 454 | 471 |
| 455 std::vector<gfx::Rect> record_rects; | 472 std::vector<gfx::Rect> record_rects; |
| 473 { | |
| 474 TRACE_EVENT0("cc", "PicturePile::Clustering"); | |
| 456 ClusterTiles(invalid_tiles, &record_rects); | 475 ClusterTiles(invalid_tiles, &record_rects); |
| 476 } | |
| 457 | 477 |
| 458 if (record_rects.empty()) | 478 if (record_rects.empty()) |
| 459 return updated; | 479 return updated; |
| 460 | 480 |
| 461 for (std::vector<gfx::Rect>::iterator it = record_rects.begin(); | 481 for (std::vector<gfx::Rect>::iterator it = record_rects.begin(); |
| 462 it != record_rects.end(); | 482 it != record_rects.end(); |
| 463 it++) { | 483 it++) { |
| 464 gfx::Rect record_rect = *it; | 484 gfx::Rect record_rect = *it; |
| 465 record_rect = PadRect(record_rect); | 485 record_rect = PadRect(record_rect); |
| 466 | 486 |
| 467 int repeat_count = std::max(1, slow_down_raster_scale_factor_for_debug_); | 487 int repeat_count = std::max(1, slow_down_raster_scale_factor_for_debug_); |
| 468 scoped_refptr<Picture> picture; | 488 scoped_refptr<Picture> picture; |
| 469 | 489 |
| 470 // Note: Currently, gathering of pixel refs when using a single | 490 // Note: Currently, gathering of pixel refs when using a single |
| 471 // raster thread doesn't provide any benefit. This might change | 491 // raster thread doesn't provide any benefit. This might change |
| 472 // in the future but we avoid it for now to reduce the cost of | 492 // in the future but we avoid it for now to reduce the cost of |
| 473 // Picture::Create. | 493 // Picture::Create. |
| 474 bool gather_pixel_refs = RasterWorkerPool::GetNumRasterThreads() > 1; | 494 bool gather_pixel_refs = RasterWorkerPool::GetNumRasterThreads() > 1; |
| 475 | 495 |
| 476 { | 496 { |
| 497 TRACE_EVENT0("cc", "PicturePile::Record"); | |
| 477 base::TimeDelta best_duration = base::TimeDelta::Max(); | 498 base::TimeDelta best_duration = base::TimeDelta::Max(); |
| 478 for (int i = 0; i < repeat_count; i++) { | 499 for (int i = 0; i < repeat_count; i++) { |
| 479 base::TimeTicks start_time = stats_instrumentation->StartRecording(); | 500 base::TimeTicks start_time = stats_instrumentation->StartRecording(); |
| 480 picture = Picture::Create(record_rect, | 501 picture = Picture::Create(record_rect, |
| 481 painter, | 502 painter, |
| 482 tile_grid_info_, | 503 tile_grid_info_, |
| 483 gather_pixel_refs, | 504 gather_pixel_refs, |
| 484 recording_mode); | 505 recording_mode); |
| 485 // Note the '&&' with previous is-suitable state. | 506 // Note the '&&' with previous is-suitable state. |
| 486 // This means that once a picture-pile becomes unsuitable for gpu | 507 // This means that once a picture-pile becomes unsuitable for gpu |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 506 for (TilingData::Iterator it(&tiling_, record_rect, include_borders); it; | 527 for (TilingData::Iterator it(&tiling_, record_rect, include_borders); it; |
| 507 ++it) { | 528 ++it) { |
| 508 const PictureMapKey& key = it.index(); | 529 const PictureMapKey& key = it.index(); |
| 509 gfx::Rect tile = PaddedRect(key); | 530 gfx::Rect tile = PaddedRect(key); |
| 510 if (record_rect.Contains(tile)) { | 531 if (record_rect.Contains(tile)) { |
| 511 PictureInfo& info = picture_map_[key]; | 532 PictureInfo& info = picture_map_[key]; |
| 512 info.SetPicture(picture); | 533 info.SetPicture(picture); |
| 513 found_tile_for_recorded_picture = true; | 534 found_tile_for_recorded_picture = true; |
| 514 } | 535 } |
| 515 } | 536 } |
| 537 TRACE_EVENT0("cc", "PicturePile::DetermineIfSolidColor"); | |
| 516 DetermineIfSolidColor(); | 538 DetermineIfSolidColor(); |
| 517 DCHECK(found_tile_for_recorded_picture); | 539 DCHECK(found_tile_for_recorded_picture); |
| 518 } | 540 } |
| 519 | 541 |
| 520 has_any_recordings_ = true; | 542 has_any_recordings_ = true; |
| 521 DCHECK(CanRasterSlowTileCheck(recorded_viewport_)); | 543 DCHECK(CanRasterSlowTileCheck(recorded_viewport_)); |
| 522 return true; | 544 return true; |
| 523 } | 545 } |
| 524 | 546 |
| 525 void PicturePile::SetEmptyBounds() { | 547 void PicturePile::SetEmptyBounds() { |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 554 if (it->second.GetPicture() != picture) | 576 if (it->second.GetPicture() != picture) |
| 555 return; | 577 return; |
| 556 } | 578 } |
| 557 skia::AnalysisCanvas canvas(recorded_viewport_.width(), | 579 skia::AnalysisCanvas canvas(recorded_viewport_.width(), |
| 558 recorded_viewport_.height()); | 580 recorded_viewport_.height()); |
| 559 picture->Raster(&canvas, NULL, Region(), 1.0f); | 581 picture->Raster(&canvas, NULL, Region(), 1.0f); |
| 560 is_solid_color_ = canvas.GetColorIfSolid(&solid_color_); | 582 is_solid_color_ = canvas.GetColorIfSolid(&solid_color_); |
| 561 } | 583 } |
| 562 | 584 |
| 563 } // namespace cc | 585 } // namespace cc |
| OLD | NEW |