FileSystem mods: Changes to snapshot file creation to remove dependencies on blobs.
[chromium-blink-merge.git] / cc / picture_pile.cc
blob1db3f4bd1cac3e150fbb1197ecbfc5e2d4d0aa3f
1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include <algorithm>
7 #include "cc/picture_pile.h"
8 #include "cc/picture_pile_impl.h"
9 #include "cc/region.h"
11 namespace {
12 // Maximum number of pictures that can overlap before we collapse them into
13 // a larger one.
14 const int kMaxOverlapping = 2;
15 // Maximum percentage area of the base picture another picture in the picture
16 // list can be. If higher, we destroy the list and recreate from scratch.
17 const float kResetThreshold = 0.7f;
18 // Layout pixel buffer around the visible layer rect to record. Any base
19 // picture that intersects the visible layer rect expanded by this distance
20 // will be recorded.
21 const int kPixelDistanceToRecord = 8000;
24 namespace cc {
26 PicturePile::PicturePile() {
29 PicturePile::~PicturePile() {
32 void PicturePile::Update(
33 ContentLayerClient* painter,
34 const Region& invalidation,
35 gfx::Rect visible_layer_rect,
36 RenderingStats* stats) {
37 gfx::Rect interest_rect = visible_layer_rect;
38 interest_rect.Inset(
39 -kPixelDistanceToRecord,
40 -kPixelDistanceToRecord,
41 -kPixelDistanceToRecord,
42 -kPixelDistanceToRecord);
43 for (Region::Iterator i(invalidation); i.has_rect(); i.next()) {
44 // Inflate all recordings from invalidations with a margin so that when
45 // scaled down to at least min_contents_scale, any final pixel touched by an
46 // invalidation can be fully rasterized by this picture.
47 gfx::Rect inflated_invalidation = i.rect();
48 inflated_invalidation.Inset(
49 -buffer_pixels(),
50 -buffer_pixels(),
51 -buffer_pixels(),
52 -buffer_pixels());
53 // Split this inflated invalidation across tile boundaries and apply it
54 // to all tiles that it touches.
55 for (TilingData::Iterator iter(&tiling_, inflated_invalidation);
56 iter; ++iter) {
57 gfx::Rect tile =
58 tiling_.TileBoundsWithBorder(iter.index_x(), iter.index_y());
59 if (!tile.Intersects(interest_rect)) {
60 // This invalidation touches a tile outside the interest rect, so
61 // just remove the entire picture list.
62 picture_list_map_.erase(iter.index());
63 continue;
66 gfx::Rect tile_invalidation =
67 gfx::IntersectRects(inflated_invalidation, tile);
68 if (tile_invalidation.IsEmpty())
69 continue;
70 PictureListMap::iterator find = picture_list_map_.find(iter.index());
71 if (find == picture_list_map_.end())
72 continue;
73 PictureList& pic_list = find->second;
74 // Leave empty pic_lists empty in case there are multiple invalidations.
75 if (!pic_list.empty())
76 InvalidateRect(pic_list, tile_invalidation);
80 // Walk through all pictures in the rect of interest and record.
81 for (TilingData::Iterator iter(&tiling_, interest_rect); iter; ++iter) {
82 // Create a picture in this list if it doesn't exist.
83 PictureList& pic_list = picture_list_map_[iter.index()];
84 if (pic_list.empty()) {
85 gfx::Rect tile =
86 tiling_.TileBoundsWithBorder(iter.index_x(), iter.index_y());
87 scoped_refptr<Picture> base_picture = Picture::Create(tile);
88 pic_list.push_back(base_picture);
91 for (PictureList::iterator pic = pic_list.begin();
92 pic != pic_list.end(); ++pic) {
93 if (!(*pic)->HasRecording())
94 (*pic)->Record(painter, stats);
98 UpdateRecordedRegion();
101 class FullyContainedPredicate {
102 public:
103 FullyContainedPredicate(gfx::Rect rect) : layer_rect_(rect) { }
104 bool operator()(const scoped_refptr<Picture>& picture) {
105 return layer_rect_.Contains(picture->LayerRect());
107 gfx::Rect layer_rect_;
110 void PicturePile::InvalidateRect(
111 PictureList& picture_list,
112 gfx::Rect invalidation) {
113 DCHECK(!picture_list.empty());
115 std::vector<PictureList::iterator> overlaps;
116 for (PictureList::iterator i = picture_list.begin();
117 i != picture_list.end(); ++i) {
118 if ((*i)->LayerRect().Contains(invalidation) && !(*i)->HasRecording())
119 return;
120 if ((*i)->LayerRect().Intersects(invalidation) && i != picture_list.begin())
121 overlaps.push_back(i);
124 gfx::Rect picture_rect = invalidation;
125 if (overlaps.size() >= kMaxOverlapping) {
126 for (size_t j = 0; j < overlaps.size(); j++)
127 picture_rect.Union((*overlaps[j])->LayerRect());
130 Picture* base_picture = picture_list.front();
131 int max_pixels = kResetThreshold * base_picture->LayerRect().size().GetArea();
132 if (picture_rect.size().GetArea() > max_pixels) {
133 // This picture list will be entirely recreated, so clear it.
134 picture_list.clear();
135 return;
138 FullyContainedPredicate pred(picture_rect);
139 picture_list.erase(std::remove_if(picture_list.begin(),
140 picture_list.end(),
141 pred),
142 picture_list.end());
143 picture_list.push_back(Picture::Create(picture_rect));
147 void PicturePile::PushPropertiesTo(PicturePileImpl* other) {
148 // TODO(enne): Don't clear clones or push anything if nothing has changed
149 // on this layer this frame.
150 PicturePileBase::PushPropertiesTo(other);
151 other->clones_.clear();
154 } // namespace cc