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

Side by Side Diff: cc/resources/picture_pile.cc

Issue 1061203002: cc: Remove invalidation history (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 8 months 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
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/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
11 #include "cc/base/region.h" 11 #include "cc/base/region.h"
12 #include "cc/resources/picture_pile_impl.h" 12 #include "cc/resources/picture_pile_impl.h"
13 #include "skia/ext/analysis_canvas.h" 13 #include "skia/ext/analysis_canvas.h"
14 14
15 namespace { 15 namespace {
16 // Layout pixel buffer around the visible layer rect to record. Any base 16 // Layout pixel buffer around the visible layer rect to record. Any base
17 // picture that intersects the visible layer rect expanded by this distance 17 // picture that intersects the visible layer rect expanded by this distance
18 // will be recorded. 18 // will be recorded.
19 const int kPixelDistanceToRecord = 8000; 19 const int kPixelDistanceToRecord = 8000;
20 // We don't perform solid color analysis on images that have more than 10 skia 20 // We don't perform solid color analysis on images that have more than 10 skia
21 // operations. 21 // operations.
22 const int kOpCountThatIsOkToAnalyze = 10; 22 const int kOpCountThatIsOkToAnalyze = 10;
23 23
24 // Dimensions of the tiles in this picture pile as well as the dimensions of 24 // Dimensions of the tiles in this picture pile as well as the dimensions of
25 // the base picture in each tile. 25 // the base picture in each tile.
26 const int kBasePictureSize = 512; 26 const int kBasePictureSize = 512;
27 27
28 // Invalidation frequency settings. kInvalidationFrequencyThreshold is a value
29 // between 0 and 1 meaning invalidation frequency between 0% and 100% that
30 // indicates when to stop invalidating offscreen regions.
31 // kFrequentInvalidationDistanceThreshold defines what it means to be
32 // "offscreen" in terms of distance to visible in css pixels.
33 // TODO(vmpstr): Remove invalidation frequency after frequently invalidated
34 // content is not painted at a higher level.
35 const float kInvalidationFrequencyThreshold = 0.75f;
36 const int kFrequentInvalidationDistanceThreshold = 1024;
37
38 // TODO(humper): The density threshold here is somewhat arbitrary; need a 28 // TODO(humper): The density threshold here is somewhat arbitrary; need a
39 // way to set // this from the command line so we can write a benchmark 29 // way to set // this from the command line so we can write a benchmark
40 // script and find a sweet spot. 30 // script and find a sweet spot.
41 const float kDensityThreshold = 0.5f; 31 const float kDensityThreshold = 0.5f;
42 32
43 bool rect_sort_y(const gfx::Rect& r1, const gfx::Rect& r2) { 33 bool rect_sort_y(const gfx::Rect& r1, const gfx::Rect& r2) {
44 return r1.y() < r2.y() || (r1.y() == r2.y() && r1.x() < r2.x()); 34 return r1.y() < r2.y() || (r1.y() == r2.y() && r1.x() < r2.x());
45 } 35 }
46 36
47 bool rect_sort_x(const gfx::Rect& r1, const gfx::Rect& r2) { 37 bool rect_sort_x(const gfx::Rect& r1, const gfx::Rect& r2) {
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
209 199
210 CreatePictures(painter, recording_mode, record_rects); 200 CreatePictures(painter, recording_mode, record_rects);
211 201
212 DetermineIfSolidColor(); 202 DetermineIfSolidColor();
213 203
214 has_any_recordings_ = true; 204 has_any_recordings_ = true;
215 DCHECK(CanRasterSlowTileCheck(recorded_viewport_)); 205 DCHECK(CanRasterSlowTileCheck(recorded_viewport_));
216 return true; 206 return true;
217 } 207 }
218 208
219 void PicturePile::DidMoveToNewCompositor() {
220 for (auto& map_pair : picture_map_)
221 map_pair.second.ResetInvalidationHistory();
222 }
223
224 bool PicturePile::ApplyInvalidationAndResize(const gfx::Rect& interest_rect, 209 bool PicturePile::ApplyInvalidationAndResize(const gfx::Rect& interest_rect,
225 Region* invalidation, 210 Region* invalidation,
226 const gfx::Size& layer_size, 211 const gfx::Size& layer_size,
227 int frame_number) { 212 int frame_number) {
228 bool updated = false; 213 bool updated = false;
229 214
230 Region synthetic_invalidation; 215 Region synthetic_invalidation;
231 gfx::Size old_tiling_size = GetSize(); 216 gfx::Size old_tiling_size = GetSize();
232 if (old_tiling_size != layer_size) { 217 if (old_tiling_size != layer_size) {
233 tiling_.SetTilingSize(layer_size); 218 tiling_.SetTilingSize(layer_size);
(...skipping 24 matching lines...) Expand all
258 tiling_.FirstBorderTileXIndexFromSrcCoord(min_tiling_size.width()); 243 tiling_.FirstBorderTileXIndexFromSrcCoord(min_tiling_size.width());
259 } 244 }
260 int min_toss_y = tiling_.num_tiles_y(); 245 int min_toss_y = tiling_.num_tiles_y();
261 if (max_tiling_size.height() > min_tiling_size.height()) { 246 if (max_tiling_size.height() > min_tiling_size.height()) {
262 min_toss_y = 247 min_toss_y =
263 tiling_.FirstBorderTileYIndexFromSrcCoord(min_tiling_size.height()); 248 tiling_.FirstBorderTileYIndexFromSrcCoord(min_tiling_size.height());
264 } 249 }
265 for (const auto& key_picture_pair : picture_map_) { 250 for (const auto& key_picture_pair : picture_map_) {
266 const PictureMapKey& key = key_picture_pair.first; 251 const PictureMapKey& key = key_picture_pair.first;
267 if (key.first < min_toss_x && key.second < min_toss_y) { 252 if (key.first < min_toss_x && key.second < min_toss_y) {
268 has_any_recordings_ |= !!key_picture_pair.second.GetPicture(); 253 has_any_recordings_ |= true;
vmpstr 2015/04/07 17:43:14 nit: = true
269 continue; 254 continue;
270 } 255 }
271 to_erase.push_back(key); 256 to_erase.push_back(key);
272 } 257 }
273 258
274 for (size_t i = 0; i < to_erase.size(); ++i) 259 for (size_t i = 0; i < to_erase.size(); ++i)
275 picture_map_.erase(to_erase[i]); 260 picture_map_.erase(to_erase[i]);
276 261
277 // If a recording is dropped and not re-recorded below, invalidate that 262 // If a recording is dropped and not re-recorded below, invalidate that
278 // full recording to cause any raster tiles that would use it to be 263 // full recording to cause any raster tiles that would use it to be
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
430 synthetic_invalidation.Union(top_rect); 415 synthetic_invalidation.Union(top_rect);
431 synthetic_invalidation.Union(bottom_rect); 416 synthetic_invalidation.Union(bottom_rect);
432 synthetic_invalidation.Union(exposed_rect); 417 synthetic_invalidation.Union(exposed_rect);
433 } 418 }
434 } 419 }
435 420
436 // Detect cases where the full pile is invalidated, in this situation we 421 // Detect cases where the full pile is invalidated, in this situation we
437 // can just drop/invalidate everything. 422 // can just drop/invalidate everything.
438 if (invalidation->Contains(gfx::Rect(old_tiling_size)) || 423 if (invalidation->Contains(gfx::Rect(old_tiling_size)) ||
439 invalidation->Contains(gfx::Rect(GetSize()))) { 424 invalidation->Contains(gfx::Rect(GetSize()))) {
440 for (auto& it : picture_map_) 425 updated = !picture_map_.empty();
441 updated = it.second.Invalidate(frame_number) || updated; 426 picture_map_.clear();
442 } else { 427 } else {
443 // Expand invalidation that is on tiles that aren't in the interest rect and 428 // Expand invalidation that is on tiles that aren't in the interest rect and
444 // will not be re-recorded below. These tiles are no longer valid and should 429 // will not be re-recorded below. These tiles are no longer valid and should
445 // be considerered fully invalid, so we can know to not keep around raster 430 // be considerered fully invalid, so we can know to not keep around raster
446 // tiles that intersect with these recording tiles. 431 // tiles that intersect with these recording tiles.
447 Region invalidation_expanded_to_full_tiles; 432 Region invalidation_expanded_to_full_tiles;
448 433
449 for (Region::Iterator i(*invalidation); i.has_rect(); i.next()) { 434 for (Region::Iterator i(*invalidation); i.has_rect(); i.next()) {
450 gfx::Rect invalid_rect = i.rect(); 435 gfx::Rect invalid_rect = i.rect();
451 436
(...skipping 19 matching lines...) Expand all
471 bool include_borders = true; 456 bool include_borders = true;
472 for (TilingData::Iterator iter(&tiling_, invalid_rect, include_borders); 457 for (TilingData::Iterator iter(&tiling_, invalid_rect, include_borders);
473 iter; 458 iter;
474 ++iter) { 459 ++iter) {
475 const PictureMapKey& key = iter.index(); 460 const PictureMapKey& key = iter.index();
476 461
477 PictureMap::iterator picture_it = picture_map_.find(key); 462 PictureMap::iterator picture_it = picture_map_.find(key);
478 if (picture_it == picture_map_.end()) 463 if (picture_it == picture_map_.end())
479 continue; 464 continue;
480 465
481 // Inform the grid cell that it has been invalidated in this frame. 466 updated = true;
482 updated = picture_it->second.Invalidate(frame_number) || updated; 467 picture_map_.erase(key);
468
483 // Invalidate drops the picture so the whole tile better be invalidated 469 // Invalidate drops the picture so the whole tile better be invalidated
484 // if it won't be re-recorded below. 470 // if it won't be re-recorded below.
485 DCHECK_IMPLIES(!tiling_.TileBounds(key.first, key.second) 471 DCHECK_IMPLIES(!tiling_.TileBounds(key.first, key.second)
486 .Intersects(interest_rect_over_tiles), 472 .Intersects(interest_rect_over_tiles),
487 invalidation_expanded_to_full_tiles.Contains( 473 invalidation_expanded_to_full_tiles.Contains(
488 tiling_.TileBounds(key.first, key.second))); 474 tiling_.TileBounds(key.first, key.second)));
489 } 475 }
490 } 476 }
491 invalidation->Union(invalidation_expanded_to_full_tiles); 477 invalidation->Union(invalidation_expanded_to_full_tiles);
492 } 478 }
493 479
494 invalidation->Union(synthetic_invalidation); 480 invalidation->Union(synthetic_invalidation);
495 return updated; 481 return updated;
496 } 482 }
497 483
498 void PicturePile::GetInvalidTileRects(const gfx::Rect& interest_rect, 484 void PicturePile::GetInvalidTileRects(const gfx::Rect& interest_rect,
499 Region* invalidation, 485 Region* invalidation,
500 const gfx::Rect& visible_layer_rect, 486 const gfx::Rect& visible_layer_rect,
501 int frame_number, 487 int frame_number,
502 std::vector<gfx::Rect>* invalid_tiles) { 488 std::vector<gfx::Rect>* invalid_tiles) {
503 // Make a list of all invalid tiles; we will attempt to 489 // Make a list of all invalid tiles; we will attempt to
504 // cluster these into multiple invalidation regions. 490 // cluster these into multiple invalidation regions.
505 bool include_borders = true; 491 bool include_borders = true;
506 for (TilingData::Iterator it(&tiling_, interest_rect, include_borders); it; 492 for (TilingData::Iterator it(&tiling_, interest_rect, include_borders); it;
507 ++it) { 493 ++it) {
508 const PictureMapKey& key = it.index(); 494 const PictureMapKey& key = it.index();
509 PictureInfo& info = picture_map_[key]; 495 if (picture_map_.find(key) == picture_map_.end())
510 496 invalid_tiles->push_back(tiling_.TileBounds(key.first, key.second));
511 gfx::Rect rect = PaddedRect(key);
512 int distance_to_visible =
513 rect.ManhattanInternalDistance(visible_layer_rect);
514
515 if (info.NeedsRecording(frame_number, distance_to_visible)) {
516 gfx::Rect tile = tiling_.TileBounds(key.first, key.second);
517 invalid_tiles->push_back(tile);
518 } else if (!info.GetPicture()) {
519 if (recorded_viewport_.Intersects(rect)) {
520 // Recorded viewport is just an optimization for a fully recorded
521 // interest rect. In this case, a tile in that rect has declined
522 // to be recorded (probably due to frequent invalidations).
523 // TODO(enne): Shrink the recorded_viewport_ rather than clearing.
524 recorded_viewport_ = gfx::Rect();
525 }
526
527 // If a tile in the interest rect is not recorded, the entire tile needs
528 // to be considered invalid, so that we know not to keep around raster
529 // tiles that intersect this recording tile.
530 invalidation->Union(tiling_.TileBounds(it.index_x(), it.index_y()));
531 }
532 } 497 }
533 } 498 }
534 499
535 void PicturePile::CreatePictures(ContentLayerClient* painter, 500 void PicturePile::CreatePictures(ContentLayerClient* painter,
536 RecordingSource::RecordingMode recording_mode, 501 RecordingSource::RecordingMode recording_mode,
537 const std::vector<gfx::Rect>& record_rects) { 502 const std::vector<gfx::Rect>& record_rects) {
538 for (const auto& record_rect : record_rects) { 503 for (const auto& record_rect : record_rects) {
539 gfx::Rect padded_record_rect = PadRect(record_rect); 504 gfx::Rect padded_record_rect = PadRect(record_rect);
540 505
541 int repeat_count = std::max(1, slow_down_raster_scale_factor_for_debug_); 506 int repeat_count = std::max(1, slow_down_raster_scale_factor_for_debug_);
(...skipping 21 matching lines...) Expand all
563 } 528 }
564 529
565 bool found_tile_for_recorded_picture = false; 530 bool found_tile_for_recorded_picture = false;
566 531
567 bool include_borders = true; 532 bool include_borders = true;
568 for (TilingData::Iterator it(&tiling_, padded_record_rect, include_borders); 533 for (TilingData::Iterator it(&tiling_, padded_record_rect, include_borders);
569 it; ++it) { 534 it; ++it) {
570 const PictureMapKey& key = it.index(); 535 const PictureMapKey& key = it.index();
571 gfx::Rect tile = PaddedRect(key); 536 gfx::Rect tile = PaddedRect(key);
572 if (padded_record_rect.Contains(tile)) { 537 if (padded_record_rect.Contains(tile)) {
573 PictureInfo& info = picture_map_[key]; 538 picture_map_[key] = picture;
574 info.SetPicture(picture);
575 found_tile_for_recorded_picture = true; 539 found_tile_for_recorded_picture = true;
576 } 540 }
577 } 541 }
578 DCHECK(found_tile_for_recorded_picture); 542 DCHECK(found_tile_for_recorded_picture);
579 } 543 }
580 } 544 }
581 545
582 scoped_refptr<RasterSource> PicturePile::CreateRasterSource( 546 scoped_refptr<RasterSource> PicturePile::CreateRasterSource(
583 bool can_use_lcd_text) const { 547 bool can_use_lcd_text) const {
584 return scoped_refptr<RasterSource>( 548 return scoped_refptr<RasterSource>(
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
650 return tile_grid_size_; 614 return tile_grid_size_;
651 } 615 }
652 616
653 bool PicturePile::CanRasterSlowTileCheck(const gfx::Rect& layer_rect) const { 617 bool PicturePile::CanRasterSlowTileCheck(const gfx::Rect& layer_rect) const {
654 bool include_borders = false; 618 bool include_borders = false;
655 for (TilingData::Iterator tile_iter(&tiling_, layer_rect, include_borders); 619 for (TilingData::Iterator tile_iter(&tiling_, layer_rect, include_borders);
656 tile_iter; ++tile_iter) { 620 tile_iter; ++tile_iter) {
657 PictureMap::const_iterator map_iter = picture_map_.find(tile_iter.index()); 621 PictureMap::const_iterator map_iter = picture_map_.find(tile_iter.index());
658 if (map_iter == picture_map_.end()) 622 if (map_iter == picture_map_.end())
659 return false; 623 return false;
660 if (!map_iter->second.GetPicture())
661 return false;
662 } 624 }
663 return true; 625 return true;
664 } 626 }
665 627
666 void PicturePile::DetermineIfSolidColor() { 628 void PicturePile::DetermineIfSolidColor() {
667 is_solid_color_ = false; 629 is_solid_color_ = false;
668 solid_color_ = SK_ColorTRANSPARENT; 630 solid_color_ = SK_ColorTRANSPARENT;
669 631
670 if (picture_map_.empty()) { 632 if (picture_map_.empty()) {
671 return; 633 return;
672 } 634 }
673 635
674 PictureMap::const_iterator it = picture_map_.begin(); 636 PictureMap::const_iterator it = picture_map_.begin();
675 const Picture* picture = it->second.GetPicture(); 637 const Picture* picture = it->second.get();
676 638
677 // Missing recordings due to frequent invalidations or being too far away 639 // Missing recordings due to frequent invalidations or being too far away
678 // from the interest rect will cause the a null picture to exist. 640 // from the interest rect will cause the a null picture to exist.
679 if (!picture) 641 if (!picture)
680 return; 642 return;
681 643
682 // Don't bother doing more work if the first image is too complicated. 644 // Don't bother doing more work if the first image is too complicated.
683 if (picture->ApproximateOpCount() > kOpCountThatIsOkToAnalyze) 645 if (picture->ApproximateOpCount() > kOpCountThatIsOkToAnalyze)
684 return; 646 return;
685 647
686 // Make sure all of the mapped images point to the same picture. 648 // Make sure all of the mapped images point to the same picture.
687 for (++it; it != picture_map_.end(); ++it) { 649 for (++it; it != picture_map_.end(); ++it) {
688 if (it->second.GetPicture() != picture) 650 if (it->second.get() != picture)
689 return; 651 return;
690 } 652 }
691 653
692 gfx::Size layer_size = GetSize(); 654 gfx::Size layer_size = GetSize();
693 skia::AnalysisCanvas canvas(layer_size.width(), layer_size.height()); 655 skia::AnalysisCanvas canvas(layer_size.width(), layer_size.height());
694 656
695 picture->Raster(&canvas, nullptr, Region(), 1.0f); 657 picture->Raster(&canvas, nullptr, Region(), 1.0f);
696 is_solid_color_ = canvas.GetColorIfSolid(&solid_color_); 658 is_solid_color_ = canvas.GetColorIfSolid(&solid_color_);
697 } 659 }
698 660
699 gfx::Rect PicturePile::PaddedRect(const PictureMapKey& key) const { 661 gfx::Rect PicturePile::PaddedRect(const PictureMapKey& key) const {
700 gfx::Rect tile = tiling_.TileBounds(key.first, key.second); 662 gfx::Rect tile = tiling_.TileBounds(key.first, key.second);
701 return PadRect(tile); 663 return PadRect(tile);
702 } 664 }
703 665
704 gfx::Rect PicturePile::PadRect(const gfx::Rect& rect) const { 666 gfx::Rect PicturePile::PadRect(const gfx::Rect& rect) const {
705 gfx::Rect padded_rect = rect; 667 gfx::Rect padded_rect = rect;
706 padded_rect.Inset(-buffer_pixels(), -buffer_pixels(), -buffer_pixels(), 668 padded_rect.Inset(-buffer_pixels(), -buffer_pixels(), -buffer_pixels(),
707 -buffer_pixels()); 669 -buffer_pixels());
708 return padded_rect; 670 return padded_rect;
709 } 671 }
710 672
711 void PicturePile::Clear() { 673 void PicturePile::Clear() {
712 picture_map_.clear(); 674 picture_map_.clear();
713 recorded_viewport_ = gfx::Rect(); 675 recorded_viewport_ = gfx::Rect();
714 has_any_recordings_ = false; 676 has_any_recordings_ = false;
715 is_solid_color_ = false; 677 is_solid_color_ = false;
716 } 678 }
717 679
718 PicturePile::PictureInfo::PictureInfo() : last_frame_number_(0) {
719 }
720
721 PicturePile::PictureInfo::~PictureInfo() {
722 }
723
724 void PicturePile::PictureInfo::AdvanceInvalidationHistory(int frame_number) {
725 DCHECK_GE(frame_number, last_frame_number_);
726 if (frame_number == last_frame_number_)
727 return;
728
729 invalidation_history_ <<= (frame_number - last_frame_number_);
730 last_frame_number_ = frame_number;
731 }
732
733 bool PicturePile::PictureInfo::Invalidate(int frame_number) {
734 AdvanceInvalidationHistory(frame_number);
735 invalidation_history_.set(0);
736
737 bool did_invalidate = !!picture_.get();
738 picture_ = NULL;
739 return did_invalidate;
740 }
741
742 bool PicturePile::PictureInfo::NeedsRecording(int frame_number,
743 int distance_to_visible) {
744 AdvanceInvalidationHistory(frame_number);
745
746 // We only need recording if we don't have a picture. Furthermore, we only
747 // need a recording if we're within frequent invalidation distance threshold
748 // or the invalidation is not frequent enough (below invalidation frequency
749 // threshold).
750 return !picture_.get() &&
751 ((distance_to_visible <= kFrequentInvalidationDistanceThreshold) ||
752 (GetInvalidationFrequency() < kInvalidationFrequencyThreshold));
753 }
754
755 void PicturePile::PictureInfo::ResetInvalidationHistory() {
756 invalidation_history_.reset();
757 last_frame_number_ = 0;
758 }
759
760 void PicturePile::SetBufferPixels(int new_buffer_pixels) { 680 void PicturePile::SetBufferPixels(int new_buffer_pixels) {
761 if (new_buffer_pixels == buffer_pixels()) 681 if (new_buffer_pixels == buffer_pixels())
762 return; 682 return;
763 683
764 Clear(); 684 Clear();
765 tiling_.SetBorderTexels(new_buffer_pixels); 685 tiling_.SetBorderTexels(new_buffer_pixels);
766 } 686 }
767 687
768 void PicturePile::PictureInfo::SetPicture(scoped_refptr<Picture> picture) {
769 picture_ = picture;
770 }
771
772 const Picture* PicturePile::PictureInfo::GetPicture() const {
773 return picture_.get();
774 }
775
776 float PicturePile::PictureInfo::GetInvalidationFrequency() const {
777 return invalidation_history_.count() /
778 static_cast<float>(INVALIDATION_FRAMES_TRACKED);
779 }
780
781 } // namespace cc 688 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698