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

Unified Diff: cc/resources/picture_pile.cc

Issue 78883002: Cluster invalidation rectangles into coherent regions to lessen SkPicture re-recording (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Decrease the density threshold from very high testing value Created 7 years, 1 month 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: cc/resources/picture_pile.cc
diff --git a/cc/resources/picture_pile.cc b/cc/resources/picture_pile.cc
index 9f485b829602fa607353e467abb82cad3e09760c..02a40927c8706914f7cefa55bddbd5285a04fb63 100644
--- a/cc/resources/picture_pile.cc
+++ b/cc/resources/picture_pile.cc
@@ -27,6 +27,84 @@ PicturePile::PicturePile() {
PicturePile::~PicturePile() {
}
+static bool rect_sort_y(const gfx::Rect &r1, const gfx::Rect &r2) {
+ return r1.y() < r2.y();
+}
+
+static bool rect_sort_x(const gfx::Rect &r1, const gfx::Rect &r2) {
+ return r1.x() < r2.x();
+}
+
+class TileClustering {
vmpstr 2013/11/20 18:02:32 Why is this a separate class? Since all of the int
humper 2013/11/20 20:47:13 No particular reason; I had initially imagined it
+ public:
+ TileClustering(const std::vector<gfx::Rect> &tiles, float thresh)
vmpstr 2013/11/20 18:02:32 nit: spacing (vector<...>& tiles) and don't abbrev
humper 2013/11/20 20:47:13 Done.
+ : total_record_area(0),
+ invalid_record_area(0),
+ clustering_threshold(thresh) {
+ gfx::Rect cur_record_rect;
+ int total_area = 0, invalid_area = 0;
+
+ for (std::vector<gfx::Rect>::iterator it = tiles.begin();
humper 2013/11/21 18:49:29 Heh, that's what I get for not testing before doin
+ it != tiles.end();
+ it++) {
+ gfx::Rect invalid_tile = *it;
+
+ // consider adding the invalid tile to the current record
+ // rectangle. Only add it if the amount of empty space created is
+ // below a density threshold.
+
+ int tile_area = invalid_tile.width() * invalid_tile.height();
+
+ gfx::Rect proposed_union = cur_record_rect;
+ proposed_union.Union(invalid_tile);
+ int proposed_area = proposed_union.width() * proposed_union.height();
+ float proposed_density =
+ static_cast<float>(invalid_area + tile_area) /
+ static_cast<float>(proposed_area);
+
+ if (proposed_density >= clustering_threshold) {
vmpstr 2013/11/20 18:02:32 What happens in the case where we have a full row
humper 2013/11/20 20:47:13 This is partially an artifact of the greedy cluste
+ // okay to add this invalid tile to the current recording rectangle
+
+ cur_record_rect = proposed_union;
+ total_area = proposed_area;
+ invalid_area += tile_area;
+ invalid_record_area += tile_area;
+ } else {
+ // adding this invalid tile to the current recording rectangle
+ // would exceed our badness threshold, so put the current rectangle
+ // in the list of recording rects, and start a new one.
+
+ record_rects.push_back(cur_record_rect);
+ total_record_area += total_area;
+ cur_record_rect = invalid_tile;
+ invalid_area = tile_area;
+ total_area = tile_area;
+ }
+ }
+
+ if (!cur_record_rect.IsEmpty()) {
+ record_rects.push_back(cur_record_rect);
+ total_record_area += total_area;
+ }
+ }
+ std::vector<gfx::Rect> getRecordRects() const {
+ return record_rects;
+ }
+
+ float density() const {
+ if (total_record_area == 0)
+ return 1;
+ return static_cast<float>(invalid_record_area) /
+ static_cast<float>(total_record_area);
+ }
+
+ private:
+ std::vector<gfx::Rect> record_rects;
vmpstr 2013/11/20 18:02:32 nit: we typically name private members with a trai
humper 2013/11/20 20:47:13 Done.
+ int total_record_area;
+ int invalid_record_area;
+ float clustering_threshold;
+};
+
bool PicturePile::Update(
ContentLayerClient* painter,
SkColor background_color,
@@ -61,51 +139,93 @@ bool PicturePile::Update(
}
}
- gfx::Rect record_rect;
+ // make a list of all invalid tiles; we will attempt to
+ // cluster these into multiple invalidation regions.
+
vmpstr 2013/11/20 18:02:32 nit: remove this line (and most trailing blank lin
humper 2013/11/20 20:47:13 Done.
+ std::vector<gfx::Rect> invalid_tiles;
+
for (TilingData::Iterator it(&tiling_, interest_rect);
it; ++it) {
const PictureMapKey& key = it.index();
const PictureInfo& info = picture_map_[key];
if (!info.picture.get()) {
- gfx::Rect tile = PaddedRect(key);
- record_rect.Union(tile);
+ gfx::Rect tile = tiling_.TileBounds(key.first, key.second);
+ invalid_tiles.push_back(tile);
+ }
+ }
+
+ std::vector<gfx::Rect> record_rects;
+
+ if (invalid_tiles.size() == 1) {
vmpstr 2013/11/20 18:02:32 Maybe make this a helper function, something along
humper 2013/11/20 20:47:13 will do.
+ // special case for common single-invalidation update
+ record_rects = invalid_tiles;
+ } else {
+ // sort the invalid tiles by y coordinate.
+
+ std::vector<gfx::Rect> invalid_tiles_vertical = invalid_tiles;
+ std::sort(invalid_tiles_vertical.begin(),
vmpstr 2013/11/20 18:02:32 Assuming that the sort totally ignores the other c
humper 2013/11/20 20:47:13 better sort would help with this, although groupin
+ invalid_tiles_vertical.end(),
+ rect_sort_y);
+ // Note: density here is somewhat arbitrary; need a way to set
+ // this from the command line so we can write a benchmark script
+ // and find a sweet spot.
+ TileClustering vertical_clustering(invalid_tiles_vertical, 0.5);
vmpstr 2013/11/20 18:02:32 nit: Make density a constant at the top please, an
humper 2013/11/20 20:47:13 Yeah, absolutely -- wasn't sure the best way to ma
+
+ std::vector<gfx::Rect> invalid_tiles_horizontal = invalid_tiles;
+ std::sort(invalid_tiles_vertical.begin(),
+ invalid_tiles_vertical.end(),
+ rect_sort_x);
+ TileClustering horizontal_clustering(invalid_tiles_vertical, 0.5);
enne (OOO) 2013/11/20 19:15:33 Is it expensive to sort and walk through all the i
humper 2013/11/20 20:47:13 Not abandoned, just not done yet. There are a cou
+
+ if (vertical_clustering.density() < horizontal_clustering.density()) {
+ record_rects = horizontal_clustering.getRecordRects();
+ } else {
+ record_rects = vertical_clustering.getRecordRects();
}
}
- if (record_rect.IsEmpty()) {
+ if (record_rects.empty()) {
if (invalidated)
UpdateRecordedRegion();
return invalidated;
}
- int repeat_count = std::max(1, slow_down_raster_scale_factor_for_debug_);
- scoped_refptr<Picture> picture = Picture::Create(record_rect);
-
- {
- base::TimeDelta best_duration = base::TimeDelta::FromInternalValue(
- std::numeric_limits<int64>::max());
- for (int i = 0; i < repeat_count; i++) {
- base::TimeTicks start_time = stats_instrumentation->StartRecording();
- picture->Record(painter, tile_grid_info_);
- base::TimeDelta duration =
- stats_instrumentation->EndRecording(start_time);
- best_duration = std::min(duration, best_duration);
+ for (std::vector<gfx::Rect>::iterator it = record_rects.begin();
+ it != record_rects.end();
+ it++) {
+ gfx::Rect record_rect = *it;
+ record_rect.Inset(-buffer_pixels(), -buffer_pixels(),
+ -buffer_pixels(), -buffer_pixels());
+
+ int repeat_count = std::max(1, slow_down_raster_scale_factor_for_debug_);
+ scoped_refptr<Picture> picture = Picture::Create(record_rect);
+
+ {
+ base::TimeDelta best_duration = base::TimeDelta::FromInternalValue(
+ std::numeric_limits<int64>::max());
+ for (int i = 0; i < repeat_count; i++) {
+ base::TimeTicks start_time = stats_instrumentation->StartRecording();
+ picture->Record(painter, tile_grid_info_);
+ base::TimeDelta duration =
+ stats_instrumentation->EndRecording(start_time);
+ best_duration = std::min(duration, best_duration);
+ }
+ int recorded_pixel_count =
+ picture->LayerRect().width() * picture->LayerRect().height();
+ stats_instrumentation->AddRecord(best_duration, recorded_pixel_count);
+ if (num_raster_threads_ > 1)
+ picture->GatherPixelRefs(tile_grid_info_);
+ picture->CloneForDrawing(num_raster_threads_);
}
- int recorded_pixel_count =
- picture->LayerRect().width() * picture->LayerRect().height();
- stats_instrumentation->AddRecord(best_duration, recorded_pixel_count);
- if (num_raster_threads_ > 1)
- picture->GatherPixelRefs(tile_grid_info_);
- picture->CloneForDrawing(num_raster_threads_);
- }
- for (TilingData::Iterator it(&tiling_, record_rect);
- it; ++it) {
- const PictureMapKey& key = it.index();
- gfx::Rect tile = PaddedRect(key);
- if (record_rect.Contains(tile)) {
- PictureInfo& info = picture_map_[key];
- info.picture = picture;
+ for (TilingData::Iterator it(&tiling_, record_rect);
+ it; ++it) {
+ const PictureMapKey& key = it.index();
+ gfx::Rect tile = PaddedRect(key);
+ if (record_rect.Contains(tile)) {
+ PictureInfo& info = picture_map_[key];
+ info.picture = picture;
+ }
}
}
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698