1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
// Copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <algorithm>
#include "cc/picture_pile.h"
#include "cc/picture_pile_impl.h"
#include "cc/region.h"
namespace {
// Maximum number of pictures that can overlap before we collapse them into
// a larger one.
const int kMaxOverlapping = 2;
// Maximum percentage area of the base picture another picture in the pile
// can be. If higher, we destroy the pile and recreate from scratch.
const float kResetThreshold = 0.7f;
}
namespace cc {
PicturePile::PicturePile() {
}
void PicturePile::Update(
ContentLayerClient* painter,
const Region& invalidation,
RenderingStats& stats) {
if (pile_.empty()) {
ResetPile(painter, stats);
return;
}
for (Region::Iterator i(invalidation); i.has_rect(); i.next())
InvalidateRect(i.rect());
for (Pile::iterator i = pile_.begin(); i != pile_.end(); ++i) {
if (!(*i)->HasRecording())
(*i)->Record(painter, stats);
}
}
class FullyContainedPredicate {
public:
FullyContainedPredicate(gfx::Rect rect) : layer_rect_(rect) { }
bool operator()(const scoped_refptr<Picture>& picture) {
return layer_rect_.Contains(picture->LayerRect());
}
gfx::Rect layer_rect_;
};
void PicturePile::InvalidateRect(gfx::Rect invalidation) {
if (invalidation.IsEmpty())
return;
// Inflate all recordings from invalidations with a margin so that when
// scaled down to at least min_contents_scale, any final pixel touched by an
// invalidation can be fully rasterized by this picture.
invalidation.Inset(
-buffer_pixels_,
-buffer_pixels_,
-buffer_pixels_,
-buffer_pixels_);
invalidation.Intersect(gfx::Rect(size_));
std::vector<Pile::iterator> overlaps;
for (Pile::iterator i = pile_.begin(); i != pile_.end(); ++i) {
if ((*i)->LayerRect().Contains(invalidation) && !(*i)->HasRecording())
return;
if ((*i)->LayerRect().Intersects(invalidation) && i != pile_.begin())
overlaps.push_back(i);
}
gfx::Rect picture_rect = invalidation;
if (overlaps.size() >= kMaxOverlapping) {
for (size_t j = 0; j < overlaps.size(); j++)
picture_rect = gfx::UnionRects(picture_rect, (*overlaps[j])->LayerRect());
}
if (picture_rect.size().GetArea() / static_cast<float>(size_.GetArea()) >
kResetThreshold)
picture_rect = gfx::Rect(size_);
FullyContainedPredicate pred(picture_rect);
pile_.erase(std::remove_if(pile_.begin(), pile_.end(), pred), pile_.end());
pile_.push_back(Picture::Create(picture_rect));
}
void PicturePile::ResetPile(ContentLayerClient* painter,
RenderingStats& stats) {
pile_.clear();
scoped_refptr<Picture> base_picture = Picture::Create(gfx::Rect(size_));
base_picture->Record(painter, stats);
pile_.push_back(base_picture);
}
void PicturePile::PushPropertiesTo(PicturePileImpl* other) {
PicturePileBase::PushPropertiesTo(other);
// Remove all old clones.
other->clones_.clear();
}
} // namespace cc
|