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.
7 #include "cc/picture_pile.h"
8 #include "cc/picture_pile_impl.h"
12 // Maximum number of pictures that can overlap before we collapse them into
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
21 const int kPixelDistanceToRecord
= 8000;
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
;
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(
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
);
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());
66 gfx::Rect tile_invalidation
=
67 gfx::IntersectRects(inflated_invalidation
, tile
);
68 if (tile_invalidation
.IsEmpty())
70 PictureListMap::iterator find
= picture_list_map_
.find(iter
.index());
71 if (find
== picture_list_map_
.end())
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()) {
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
{
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())
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();
138 FullyContainedPredicate
pred(picture_rect
);
139 picture_list
.erase(std::remove_if(picture_list
.begin(),
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();