12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "cc/resources/picture_pile.h"
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <algorithm>
84e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <limits>
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <vector>
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/base/region.h"
124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "cc/debug/rendering_stats_instrumentation.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/resources/picture_pile_impl.h"
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "cc/resources/raster_worker_pool.h"
15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "cc/resources/tile_priority.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Layout pixel buffer around the visible layer rect to record.  Any base
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// picture that intersects the visible layer rect expanded by this distance
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// will be recorded.
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kPixelDistanceToRecord = 8000;
221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// We don't perform solid color analysis on images that have more than 10 skia
231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// operations.
241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst int kOpCountThatIsOkToAnalyze = 10;
25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// TODO(humper): The density threshold here is somewhat arbitrary; need a
27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// way to set // this from the command line so we can write a benchmark
28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// script and find a sweet spot.
29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const float kDensityThreshold = 0.5f;
30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
31116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool rect_sort_y(const gfx::Rect& r1, const gfx::Rect& r2) {
32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return r1.y() < r2.y() || (r1.y() == r2.y() && r1.x() < r2.x());
33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
35116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool rect_sort_x(const gfx::Rect& r1, const gfx::Rect& r2) {
36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return r1.x() < r2.x() || (r1.x() == r2.x() && r1.y() < r2.y());
37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
39116680a4aac90f2aa7413d9095a592090648e557Ben Murdochfloat PerformClustering(const std::vector<gfx::Rect>& tiles,
40116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                        std::vector<gfx::Rect>* clustered_rects) {
41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // These variables track the record area and invalid area
42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // for the entire clustering
43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int total_record_area = 0;
44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int total_invalid_area = 0;
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // These variables track the record area and invalid area
47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // for the current cluster being constructed.
48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  gfx::Rect cur_record_rect;
49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int cluster_record_area = 0, cluster_invalid_area = 0;
50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (std::vector<gfx::Rect>::const_iterator it = tiles.begin();
52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        it != tiles.end();
53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        it++) {
54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    gfx::Rect invalid_tile = *it;
55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // For each tile, we consider adding the invalid tile to the
57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // current record rectangle.  Only add it if the amount of empty
58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // space created is below a density threshold.
59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    int tile_area = invalid_tile.width() * invalid_tile.height();
60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    gfx::Rect proposed_union = cur_record_rect;
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    proposed_union.Union(invalid_tile);
63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    int proposed_area = proposed_union.width() * proposed_union.height();
64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    float proposed_density =
65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      static_cast<float>(cluster_invalid_area + tile_area) /
66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      static_cast<float>(proposed_area);
67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (proposed_density >= kDensityThreshold) {
69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      // It's okay to add this invalid tile to the
70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      // current recording rectangle.
71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      cur_record_rect = proposed_union;
72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      cluster_record_area = proposed_area;
73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      cluster_invalid_area += tile_area;
74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      total_invalid_area += tile_area;
75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    } else {
76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      // Adding this invalid tile to the current recording rectangle
77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      // would exceed our badness threshold, so put the current rectangle
78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      // in the list of recording rects, and start a new one.
79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      clustered_rects->push_back(cur_record_rect);
80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      total_record_area += cluster_record_area;
81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      cur_record_rect = invalid_tile;
82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      cluster_invalid_area = tile_area;
83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      cluster_record_area = tile_area;
84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(!cur_record_rect.IsEmpty());
88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  clustered_rects->push_back(cur_record_rect);
89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  total_record_area += cluster_record_area;;
90f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_NE(total_record_area, 0);
92f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return static_cast<float>(total_invalid_area) /
94f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)         static_cast<float>(total_record_area);
95116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
96f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)float ClusterTiles(const std::vector<gfx::Rect>& invalid_tiles,
98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                   std::vector<gfx::Rect>* record_rects) {
99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  TRACE_EVENT1("cc", "ClusterTiles",
100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)               "count",
101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)               invalid_tiles.size());
102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (invalid_tiles.size() <= 1) {
104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Quickly handle the special case for common
105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // single-invalidation update, and also the less common
106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // case of no tiles passed in.
107f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    *record_rects = invalid_tiles;
108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return 1;
109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Sort the invalid tiles by y coordinate.
112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::vector<gfx::Rect> invalid_tiles_vertical = invalid_tiles;
113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::sort(invalid_tiles_vertical.begin(),
114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            invalid_tiles_vertical.end(),
115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            rect_sort_y);
116f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  float vertical_density;
118f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::vector<gfx::Rect> vertical_clustering;
119116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  vertical_density = PerformClustering(invalid_tiles_vertical,
120116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       &vertical_clustering);
121116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
122116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // If vertical density is optimal, then we can return early.
123116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (vertical_density == 1.f) {
124116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    *record_rects = vertical_clustering;
125116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return vertical_density;
126116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
127f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Now try again with a horizontal sort, see which one is best
129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::vector<gfx::Rect> invalid_tiles_horizontal = invalid_tiles;
130116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  std::sort(invalid_tiles_horizontal.begin(),
131116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch            invalid_tiles_horizontal.end(),
132f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            rect_sort_x);
133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
134f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  float horizontal_density;
135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::vector<gfx::Rect> horizontal_clustering;
136116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  horizontal_density = PerformClustering(invalid_tiles_horizontal,
137116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                         &horizontal_clustering);
138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (vertical_density < horizontal_density) {
140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    *record_rects = horizontal_clustering;
141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return horizontal_density;
142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  *record_rects = vertical_clustering;
145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return vertical_density;
146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
147f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}  // namespace
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace cc {
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1525b62eb5758cb7b791cfdd45cf78f35dc060631b6Ben MurdochPicturePile::PicturePile()
1535b62eb5758cb7b791cfdd45cf78f35dc060631b6Ben Murdoch    : is_suitable_for_gpu_rasterization_(true),
1545b62eb5758cb7b791cfdd45cf78f35dc060631b6Ben Murdoch      pixel_record_distance_(kPixelDistanceToRecord) {
1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)PicturePile::~PicturePile() {
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
160f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool PicturePile::UpdateAndExpandInvalidation(
161f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    ContentLayerClient* painter,
162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    Region* invalidation,
163f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    SkColor background_color,
164f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    bool contents_opaque,
165f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    bool contents_fill_bounds_completely,
166116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const gfx::Size& layer_size,
167f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const gfx::Rect& visible_layer_rect,
168f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    int frame_number,
169f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    Picture::RecordingMode recording_mode,
170f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    RenderingStatsInstrumentation* stats_instrumentation) {
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  background_color_ = background_color;
172868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  contents_opaque_ = contents_opaque;
173effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  contents_fill_bounds_completely_ = contents_fill_bounds_completely;
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
175116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  bool updated = false;
176116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
177116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  Region resize_invalidation;
178116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  gfx::Size old_tiling_size = tiling_size();
179116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (old_tiling_size != layer_size) {
180116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    tiling_.SetTilingSize(layer_size);
181116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    updated = true;
182116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
183116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect interest_rect = visible_layer_rect;
1855b62eb5758cb7b791cfdd45cf78f35dc060631b6Ben Murdoch  interest_rect.Inset(-pixel_record_distance_, -pixel_record_distance_);
18623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  recorded_viewport_ = interest_rect;
187116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  recorded_viewport_.Intersect(gfx::Rect(tiling_size()));
1881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
189f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  gfx::Rect interest_rect_over_tiles =
190f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      tiling_.ExpandRectToTileBounds(interest_rect);
191f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
192757e6d30528497c763bce864b552885d3c119fc7enne  gfx::Size min_tiling_size(
193757e6d30528497c763bce864b552885d3c119fc7enne      std::min(tiling_size().width(), old_tiling_size.width()),
194757e6d30528497c763bce864b552885d3c119fc7enne      std::min(tiling_size().height(), old_tiling_size.height()));
195757e6d30528497c763bce864b552885d3c119fc7enne  gfx::Size max_tiling_size(
196757e6d30528497c763bce864b552885d3c119fc7enne      std::max(tiling_size().width(), old_tiling_size.width()),
197757e6d30528497c763bce864b552885d3c119fc7enne      std::max(tiling_size().height(), old_tiling_size.height()));
198757e6d30528497c763bce864b552885d3c119fc7enne
199116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (old_tiling_size != layer_size) {
200116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    has_any_recordings_ = false;
201f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
202757e6d30528497c763bce864b552885d3c119fc7enne    // Drop recordings that are outside the new or old layer bounds or that
203757e6d30528497c763bce864b552885d3c119fc7enne    // changed size.  Newly exposed areas are considered invalidated.
204757e6d30528497c763bce864b552885d3c119fc7enne    // Previously exposed areas that are now outside of bounds also need to
205757e6d30528497c763bce864b552885d3c119fc7enne    // be invalidated, as they may become part of raster when scale < 1.
206116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    std::vector<PictureMapKey> to_erase;
207116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    int min_toss_x = tiling_.num_tiles_x();
208757e6d30528497c763bce864b552885d3c119fc7enne    if (max_tiling_size.width() > min_tiling_size.width()) {
209116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      min_toss_x =
210757e6d30528497c763bce864b552885d3c119fc7enne          tiling_.FirstBorderTileXIndexFromSrcCoord(min_tiling_size.width());
211116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
212116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    int min_toss_y = tiling_.num_tiles_y();
213757e6d30528497c763bce864b552885d3c119fc7enne    if (max_tiling_size.height() > min_tiling_size.height()) {
214116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      min_toss_y =
215757e6d30528497c763bce864b552885d3c119fc7enne          tiling_.FirstBorderTileYIndexFromSrcCoord(min_tiling_size.height());
216116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
217116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    for (PictureMap::const_iterator it = picture_map_.begin();
218116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch         it != picture_map_.end();
219116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch         ++it) {
220116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      const PictureMapKey& key = it->first;
221116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      if (key.first < min_toss_x && key.second < min_toss_y) {
222116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        has_any_recordings_ |= !!it->second.GetPicture();
223116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        continue;
224116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      }
225116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      to_erase.push_back(key);
226116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
227116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
228116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    for (size_t i = 0; i < to_erase.size(); ++i)
229116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      picture_map_.erase(to_erase[i]);
230116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
231116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // If a recording is dropped and not re-recorded below, invalidate that
232116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // full recording to cause any raster tiles that would use it to be
233116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // dropped.
234757e6d30528497c763bce864b552885d3c119fc7enne    // If the recording will be replaced below, invalidate newly exposed
235757e6d30528497c763bce864b552885d3c119fc7enne    // areas and previously exposed areas to force raster tiles that include the
236757e6d30528497c763bce864b552885d3c119fc7enne    // old recording to know there is new recording to display.
237757e6d30528497c763bce864b552885d3c119fc7enne    gfx::Rect min_tiling_rect_over_tiles =
238757e6d30528497c763bce864b552885d3c119fc7enne        tiling_.ExpandRectToTileBounds(gfx::Rect(min_tiling_size));
239116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (min_toss_x < tiling_.num_tiles_x()) {
2401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // The bounds which we want to invalidate are the tiles along the old
241757e6d30528497c763bce864b552885d3c119fc7enne      // edge of the pile when expanding, or the new edge of the pile when
242757e6d30528497c763bce864b552885d3c119fc7enne      // shrinking. In either case, it's the difference of the two, so we'll
243757e6d30528497c763bce864b552885d3c119fc7enne      // call this bounding box the DELTA EDGE RECT.
2441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      //
245757e6d30528497c763bce864b552885d3c119fc7enne      // In the picture below, the delta edge rect would be the bounding box of
246757e6d30528497c763bce864b552885d3c119fc7enne      // tiles {h,i,j}. |min_toss_x| would be equal to the horizontal index of
247757e6d30528497c763bce864b552885d3c119fc7enne      // the same tiles.
2481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      //
249757e6d30528497c763bce864b552885d3c119fc7enne      //  min pile edge-v  max pile edge-v
2501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // ---------------+ - - - - - - - -+
2511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // mmppssvvyybbeeh|h               .
2521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // mmppssvvyybbeeh|h               .
2531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // nnqqttwwzzccffi|i               .
2541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // nnqqttwwzzccffi|i               .
2551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // oorruuxxaaddggj|j               .
2561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // oorruuxxaaddggj|j               .
257757e6d30528497c763bce864b552885d3c119fc7enne      // ---------------+ - - - - - - - -+ <- min pile edge
2581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      //                                 .
259757e6d30528497c763bce864b552885d3c119fc7enne      //  - - - - - - - - - - - - - - - -+ <- max pile edge
2601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      //
2611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // If you were to slide a vertical beam from the left edge of the
262757e6d30528497c763bce864b552885d3c119fc7enne      // delta edge rect toward the right, it would either hit the right edge
263757e6d30528497c763bce864b552885d3c119fc7enne      // of the delta edge rect, or the interest rect (expanded to the bounds
2641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // of the tiles it touches). The same is true for a beam parallel to
265757e6d30528497c763bce864b552885d3c119fc7enne      // any of the four edges, sliding across the delta edge rect. We use
2661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // the union of these four rectangles generated by these beams to
267757e6d30528497c763bce864b552885d3c119fc7enne      // determine which part of the delta edge rect is outside of the expanded
2681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // interest rect.
2691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      //
270757e6d30528497c763bce864b552885d3c119fc7enne      // Case 1: Intersect rect is outside the delta edge rect. It can be
2711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // either on the left or the right. The |left_rect| and |right_rect|,
2721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // cover this case, one will be empty and one will cover the full
273757e6d30528497c763bce864b552885d3c119fc7enne      // delta edge rect. In the picture below, |left_rect| would cover the
274757e6d30528497c763bce864b552885d3c119fc7enne      // delta edge rect, and |right_rect| would be empty.
2751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // +----------------------+ |^^^^^^^^^^^^^^^|
276757e6d30528497c763bce864b552885d3c119fc7enne      // |===> DELTA EDGE RECT  | |               |
2771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // |===>                  | | INTEREST RECT |
2781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // |===>                  | |               |
2791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // |===>                  | |               |
2801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // +----------------------+ |vvvvvvvvvvvvvvv|
2811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      //
282757e6d30528497c763bce864b552885d3c119fc7enne      // Case 2: Interest rect is inside the delta edge rect. It will always
283757e6d30528497c763bce864b552885d3c119fc7enne      // fill the entire delta edge rect horizontally since the old edge rect
2841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // is a single tile wide, and the interest rect has been expanded to the
2851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // bounds of the tiles it touches. In this case the |left_rect| and
2861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // |right_rect| will be empty, but the case is handled by the |top_rect|
2871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // and |bottom_rect|. In the picture below, neither the |top_rect| nor
2881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // |bottom_rect| would empty, they would each cover the area of the old
2891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // edge rect outside the expanded interest rect.
2901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // +-----------------+
2911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // |:::::::::::::::::|
2921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // |:::::::::::::::::|
2931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // |vvvvvvvvvvvvvvvvv|
2941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // |                 |
2951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // +-----------------+
2961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // | INTEREST RECT   |
2971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // |                 |
2981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // +-----------------+
2991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // |                 |
300757e6d30528497c763bce864b552885d3c119fc7enne      // | DELTA EDGE RECT |
3011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // +-----------------+
3021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      //
3031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // Lastly, we need to consider tiles inside the expanded interest rect.
3041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // For those tiles, we want to invalidate exactly the newly exposed
305757e6d30528497c763bce864b552885d3c119fc7enne      // pixels. In the picture below the tiles in the delta edge rect have
306757e6d30528497c763bce864b552885d3c119fc7enne      // been resized and the area covered by periods must be invalidated. The
3071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // |exposed_rect| will cover exactly that area.
308757e6d30528497c763bce864b552885d3c119fc7enne      //           v-min pile edge
3091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // +---------+-------+
3101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // |         ........|
3111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // |         ........|
312757e6d30528497c763bce864b552885d3c119fc7enne      // | DELTA EDGE.RECT.|
3131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // |         ........|
3141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // |         ........|
3151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // |         ........|
3161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // |         ........|
3171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // |         ........|
3181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // |         ........|
3191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // +---------+-------+
3201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      int left = tiling_.TilePositionX(min_toss_x);
3221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      int right = left + tiling_.TileSizeX(min_toss_x);
323757e6d30528497c763bce864b552885d3c119fc7enne      int top = min_tiling_rect_over_tiles.y();
324757e6d30528497c763bce864b552885d3c119fc7enne      int bottom = min_tiling_rect_over_tiles.bottom();
3251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      int left_until = std::min(interest_rect_over_tiles.x(), right);
3271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      int right_until = std::max(interest_rect_over_tiles.right(), left);
3281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      int top_until = std::min(interest_rect_over_tiles.y(), bottom);
3291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      int bottom_until = std::max(interest_rect_over_tiles.bottom(), top);
3301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
331757e6d30528497c763bce864b552885d3c119fc7enne      int exposed_left = min_tiling_size.width();
332757e6d30528497c763bce864b552885d3c119fc7enne      int exposed_left_until = max_tiling_size.width();
3331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      int exposed_top = top;
334757e6d30528497c763bce864b552885d3c119fc7enne      int exposed_bottom = max_tiling_size.height();
3351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      DCHECK_GE(exposed_left, left);
3361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      gfx::Rect left_rect(left, top, left_until - left, bottom - top);
3381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      gfx::Rect right_rect(right_until, top, right - right_until, bottom - top);
3391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      gfx::Rect top_rect(left, top, right - left, top_until - top);
3401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      gfx::Rect bottom_rect(
3411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          left, bottom_until, right - left, bottom - bottom_until);
3421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      gfx::Rect exposed_rect(exposed_left,
3431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             exposed_top,
3441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             exposed_left_until - exposed_left,
3451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             exposed_bottom - exposed_top);
3461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      resize_invalidation.Union(left_rect);
3471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      resize_invalidation.Union(right_rect);
3481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      resize_invalidation.Union(top_rect);
3491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      resize_invalidation.Union(bottom_rect);
3501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      resize_invalidation.Union(exposed_rect);
351116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
352116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (min_toss_y < tiling_.num_tiles_y()) {
3531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // The same thing occurs here as in the case above, but the invalidation
354757e6d30528497c763bce864b552885d3c119fc7enne      // rect is the bounding box around the bottom row of tiles in the min
3551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // pile. This would be tiles {o,r,u,x,a,d,g,j} in the above picture.
3561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      int top = tiling_.TilePositionY(min_toss_y);
3581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      int bottom = top + tiling_.TileSizeY(min_toss_y);
359757e6d30528497c763bce864b552885d3c119fc7enne      int left = min_tiling_rect_over_tiles.x();
360757e6d30528497c763bce864b552885d3c119fc7enne      int right = min_tiling_rect_over_tiles.right();
3611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      int top_until = std::min(interest_rect_over_tiles.y(), bottom);
3631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      int bottom_until = std::max(interest_rect_over_tiles.bottom(), top);
3641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      int left_until = std::min(interest_rect_over_tiles.x(), right);
3651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      int right_until = std::max(interest_rect_over_tiles.right(), left);
3661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
367757e6d30528497c763bce864b552885d3c119fc7enne      int exposed_top = min_tiling_size.height();
368757e6d30528497c763bce864b552885d3c119fc7enne      int exposed_top_until = max_tiling_size.height();
3691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      int exposed_left = left;
370757e6d30528497c763bce864b552885d3c119fc7enne      int exposed_right = max_tiling_size.width();
3711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      DCHECK_GE(exposed_top, top);
3721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      gfx::Rect left_rect(left, top, left_until - left, bottom - top);
3741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      gfx::Rect right_rect(right_until, top, right - right_until, bottom - top);
3751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      gfx::Rect top_rect(left, top, right - left, top_until - top);
3761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      gfx::Rect bottom_rect(
3771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          left, bottom_until, right - left, bottom - bottom_until);
3781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      gfx::Rect exposed_rect(exposed_left,
3791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             exposed_top,
3801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             exposed_right - exposed_left,
3811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             exposed_top_until - exposed_top);
3821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      resize_invalidation.Union(left_rect);
3831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      resize_invalidation.Union(right_rect);
3841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      resize_invalidation.Union(top_rect);
3851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      resize_invalidation.Union(bottom_rect);
3861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      resize_invalidation.Union(exposed_rect);
387116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
388116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
389116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
3901675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch  // Detect cases where the full pile is invalidated, in this situation we
3911675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch  // can just drop/invalidate everything.
3921675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch  if (invalidation->Contains(gfx::Rect(old_tiling_size)) ||
3931675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch      invalidation->Contains(gfx::Rect(tiling_size()))) {
3941675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch    for (auto& it : picture_map_)
3951675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch      updated = it.second.Invalidate(frame_number) || updated;
3961675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch  } else {
3975b62eb5758cb7b791cfdd45cf78f35dc060631b6Ben Murdoch    // Expand invalidation that is on tiles that aren't in the interest rect and
3985b62eb5758cb7b791cfdd45cf78f35dc060631b6Ben Murdoch    // will not be re-recorded below. These tiles are no longer valid and should
3995b62eb5758cb7b791cfdd45cf78f35dc060631b6Ben Murdoch    // be considerered fully invalid, so we can know to not keep around raster
4005b62eb5758cb7b791cfdd45cf78f35dc060631b6Ben Murdoch    // tiles that intersect with these recording tiles.
4011675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch    Region invalidation_expanded_to_full_tiles;
4021675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch
4031675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch    for (Region::Iterator i(*invalidation); i.has_rect(); i.next()) {
4041675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch      gfx::Rect invalid_rect = i.rect();
4051675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch
4065b62eb5758cb7b791cfdd45cf78f35dc060631b6Ben Murdoch      // This rect covers the bounds (excluding borders) of all tiles whose
4075b62eb5758cb7b791cfdd45cf78f35dc060631b6Ben Murdoch      // bounds (including borders) touch the |interest_rect|. This matches
4085b62eb5758cb7b791cfdd45cf78f35dc060631b6Ben Murdoch      // the iteration of the |invalid_rect| below which includes borders when
4095b62eb5758cb7b791cfdd45cf78f35dc060631b6Ben Murdoch      // calling Invalidate() on pictures.
4105b62eb5758cb7b791cfdd45cf78f35dc060631b6Ben Murdoch      gfx::Rect invalid_rect_outside_interest_rect_tiles =
4115b62eb5758cb7b791cfdd45cf78f35dc060631b6Ben Murdoch          tiling_.ExpandRectToTileBounds(invalid_rect);
4125b62eb5758cb7b791cfdd45cf78f35dc060631b6Ben Murdoch      // We subtract the |interest_rect_over_tiles| which represents the bounds
4135b62eb5758cb7b791cfdd45cf78f35dc060631b6Ben Murdoch      // of tiles that will be re-recorded below. This matches the iteration of
4145b62eb5758cb7b791cfdd45cf78f35dc060631b6Ben Murdoch      // |interest_rect| below which includes borders.
4151675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch      // TODO(danakj): We should have a Rect-subtract-Rect-to-2-rects operator
4161675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch      // instead of using Rect::Subtract which gives you the bounding box of the
4171675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch      // subtraction.
4181675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch      invalid_rect_outside_interest_rect_tiles.Subtract(
4191675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch          interest_rect_over_tiles);
4205b62eb5758cb7b791cfdd45cf78f35dc060631b6Ben Murdoch      invalidation_expanded_to_full_tiles.Union(
4215b62eb5758cb7b791cfdd45cf78f35dc060631b6Ben Murdoch          invalid_rect_outside_interest_rect_tiles);
4221675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch
4231675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch      // Split this inflated invalidation across tile boundaries and apply it
4241675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch      // to all tiles that it touches.
4251675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch      bool include_borders = true;
4261675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch      for (TilingData::Iterator iter(&tiling_, invalid_rect, include_borders);
4271675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch           iter;
4281675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch           ++iter) {
4291675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch        const PictureMapKey& key = iter.index();
4301675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch
4311675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch        PictureMap::iterator picture_it = picture_map_.find(key);
4321675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch        if (picture_it == picture_map_.end())
4331675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch          continue;
4341675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch
4351675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch        // Inform the grid cell that it has been invalidated in this frame.
4361675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch        updated = picture_it->second.Invalidate(frame_number) || updated;
4371675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch        // Invalidate drops the picture so the whole tile better be invalidated
4381675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch        // if it won't be re-recorded below.
4391675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch        DCHECK(tiling_.TileBounds(key.first, key.second)
4401675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch                   .Intersects(interest_rect_over_tiles) ||
4411675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch               invalidation_expanded_to_full_tiles.Contains(
4421675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch                   tiling_.TileBounds(key.first, key.second)));
4431675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch      }
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4451675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch    invalidation->Union(invalidation_expanded_to_full_tiles);
4461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
448116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  invalidation->Union(resize_invalidation);
449f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
450f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Make a list of all invalid tiles; we will attempt to
451f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // cluster these into multiple invalidation regions.
452f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::vector<gfx::Rect> invalid_tiles;
45323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  bool include_borders = true;
45423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  for (TilingData::Iterator it(&tiling_, interest_rect, include_borders); it;
45523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)       ++it) {
4561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const PictureMapKey& key = it.index();
457a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    PictureInfo& info = picture_map_[key];
458a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
459a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    gfx::Rect rect = PaddedRect(key);
460a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    int distance_to_visible =
461a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        rect.ManhattanInternalDistance(visible_layer_rect);
462a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
463a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (info.NeedsRecording(frame_number, distance_to_visible)) {
464f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      gfx::Rect tile = tiling_.TileBounds(key.first, key.second);
465f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      invalid_tiles.push_back(tile);
466f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    } else if (!info.GetPicture()) {
467f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      if (recorded_viewport_.Intersects(rect)) {
468f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        // Recorded viewport is just an optimization for a fully recorded
469f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        // interest rect.  In this case, a tile in that rect has declined
470f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        // to be recorded (probably due to frequent invalidations).
471f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        // TODO(enne): Shrink the recorded_viewport_ rather than clearing.
472f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        recorded_viewport_ = gfx::Rect();
473f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      }
474f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
475f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // If a tile in the interest rect is not recorded, the entire tile needs
476f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // to be considered invalid, so that we know not to keep around raster
477f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // tiles that intersect this recording tile.
478f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      invalidation->Union(tiling_.TileBounds(it.index_x(), it.index_y()));
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
482f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::vector<gfx::Rect> record_rects;
483f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ClusterTiles(invalid_tiles, &record_rects);
484f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
48523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (record_rects.empty())
486116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return updated;
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
488f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (std::vector<gfx::Rect>::iterator it = record_rects.begin();
489f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)       it != record_rects.end();
490f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)       it++) {
491f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    gfx::Rect record_rect = *it;
492f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    record_rect = PadRect(record_rect);
493f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
494f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    int repeat_count = std::max(1, slow_down_raster_scale_factor_for_debug_);
4955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_refptr<Picture> picture;
4965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Note: Currently, gathering of pixel refs when using a single
4985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // raster thread doesn't provide any benefit. This might change
4995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // in the future but we avoid it for now to reduce the cost of
5005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Picture::Create.
50103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    bool gather_pixel_refs = RasterWorkerPool::GetNumRasterThreads() > 1;
502f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
503f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    {
504a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::TimeDelta best_duration = base::TimeDelta::Max();
505f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      for (int i = 0; i < repeat_count; i++) {
506f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        base::TimeTicks start_time = stats_instrumentation->StartRecording();
5075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        picture = Picture::Create(record_rect,
5085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                  painter,
5095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                  tile_grid_info_,
5105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                  gather_pixel_refs,
511010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                  recording_mode);
512a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        // Note the '&&' with previous is-suitable state.
513a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        // This means that once a picture-pile becomes unsuitable for gpu
514a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        // rasterization due to some content, it will continue to be unsuitable
515a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        // even if that content is replaced by gpu-friendly content.
516a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        // This is an optimization to avoid iterating though all pictures in
517a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        // the pile after each invalidation.
518a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        is_suitable_for_gpu_rasterization_ &=
519a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch            picture->IsSuitableForGpuRasterization();
52003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        has_text_ |= picture->HasText();
521f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        base::TimeDelta duration =
522f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            stats_instrumentation->EndRecording(start_time);
523f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        best_duration = std::min(duration, best_duration);
524f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
525f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      int recorded_pixel_count =
526f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          picture->LayerRect().width() * picture->LayerRect().height();
527f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      stats_instrumentation->AddRecord(best_duration, recorded_pixel_count);
5281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
53023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    bool found_tile_for_recorded_picture = false;
53123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
53223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    bool include_borders = true;
53323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    for (TilingData::Iterator it(&tiling_, record_rect, include_borders); it;
53423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)         ++it) {
535f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      const PictureMapKey& key = it.index();
536f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      gfx::Rect tile = PaddedRect(key);
537f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (record_rect.Contains(tile)) {
538f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        PictureInfo& info = picture_map_[key];
539a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        info.SetPicture(picture);
54023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        found_tile_for_recorded_picture = true;
541f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
5421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
5431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DetermineIfSolidColor();
54423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    DCHECK(found_tile_for_recorded_picture);
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
54723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  has_any_recordings_ = true;
54823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DCHECK(CanRasterSlowTileCheck(recorded_viewport_));
5491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return true;
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
552116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid PicturePile::SetEmptyBounds() {
553116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  tiling_.SetTilingSize(gfx::Size());
554116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  picture_map_.clear();
555116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  has_any_recordings_ = false;
556116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  recorded_viewport_ = gfx::Rect();
557116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
558116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
5591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid PicturePile::DetermineIfSolidColor() {
5601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  is_solid_color_ = false;
5611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  solid_color_ = SK_ColorTRANSPARENT;
5621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (picture_map_.empty()) {
5641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
5651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
5661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  PictureMap::const_iterator it = picture_map_.begin();
5681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const Picture* picture = it->second.GetPicture();
5691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Missing recordings due to frequent invalidations or being too far away
5711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // from the interest rect will cause the a null picture to exist.
5721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!picture)
5731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
5741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Don't bother doing more work if the first image is too complicated.
5761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (picture->ApproximateOpCount() > kOpCountThatIsOkToAnalyze)
5771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
5781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Make sure all of the mapped images point to the same picture.
5801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (++it; it != picture_map_.end(); ++it) {
5811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (it->second.GetPicture() != picture)
5821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return;
5831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
5841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  skia::AnalysisCanvas canvas(recorded_viewport_.width(),
5851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                              recorded_viewport_.height());
5865b892326406927b709cdaf6c384d4ababf456332Ben Murdoch  canvas.translate(-recorded_viewport_.x(), -recorded_viewport_.y());
5875b892326406927b709cdaf6c384d4ababf456332Ben Murdoch  picture->Raster(&canvas, nullptr, Region(), 1.0f);
5881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  is_solid_color_ = canvas.GetColorIfSolid(&solid_color_);
5891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
5901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace cc
592