OLD | NEW |
---|---|
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <algorithm> | 5 #include <algorithm> |
6 | 6 |
7 #include "cc/picture_pile.h" | 7 #include "cc/picture_pile.h" |
8 #include "cc/picture_pile_impl.h" | 8 #include "cc/picture_pile_impl.h" |
9 | 9 |
10 namespace { | 10 namespace { |
11 // Maximum number of pictures that can overlap before we collapse them into | 11 // Maximum number of pictures that can overlap before we collapse them into |
12 // a larger one. | 12 // a larger one. |
13 const int kMaxOverlapping = 2; | 13 const int kMaxOverlapping = 2; |
14 // Maximum percentage area of the base picture another picture in the pile | 14 // Maximum percentage area of the base picture another picture in the pile |
15 // can be. If higher, we destroy the pile and recreate from scratch. | 15 // can be. If higher, we destroy the pile and recreate from scratch. |
16 const float kResetThreshold = 0.7f; | 16 const float kResetThreshold = 0.7f; |
17 } | 17 } |
18 | 18 |
19 namespace cc { | 19 namespace cc { |
20 | 20 |
21 PicturePile::PicturePile() { | 21 PicturePile::PicturePile() |
22 : min_contents_scale_(0), | |
23 buffer_pixels_(0) { | |
24 SetMinContentsScale(1); | |
22 } | 25 } |
23 | 26 |
24 PicturePile::~PicturePile() { | 27 PicturePile::~PicturePile() { |
25 } | 28 } |
26 | 29 |
27 void PicturePile::Resize(gfx::Size size) { | 30 void PicturePile::Resize(gfx::Size size) { |
28 if (size_ == size) | 31 if (size_ == size) |
29 return; | 32 return; |
30 | 33 |
31 pile_.clear(); | 34 pile_.clear(); |
32 size_ = size; | 35 size_ = size; |
33 } | 36 } |
34 | 37 |
38 void PicturePile::SetMinContentsScale(float min_contents_scale) { | |
39 DCHECK(min_contents_scale); | |
40 if (min_contents_scale_ == min_contents_scale) | |
41 return; | |
42 | |
43 pile_.clear(); | |
44 min_contents_scale_ = min_contents_scale; | |
45 | |
46 // Picture contents are played back scaled. When the final contents scale is | |
47 // less than 1 (i.e. low res), then multiple recorded pixels will be used | |
48 // to raster one final pixel. To avoid splitting a final pixel across | |
49 // pictures (which would result in incorrect rasterization due to blending), a | |
50 // buffer margin is added so that any picture can be snapped to integral | |
51 // final pixels. | |
52 // | |
53 // For example, if a 1/4 contents scale is used, then that would be 3 buffer | |
54 // pixels, since that's the minimum number of pixels to add so that resulting | |
55 // content can be snapped to a four pixel aligned grid. | |
56 buffer_pixels_ = static_cast<int>(ceil(1 / min_contents_scale_) - 1); | |
57 buffer_pixels_ = std::max(0, buffer_pixels_); | |
58 } | |
59 | |
35 void PicturePile::Update( | 60 void PicturePile::Update( |
36 ContentLayerClient* painter, | 61 ContentLayerClient* painter, |
37 const Region& invalidation, | 62 const Region& invalidation, |
38 RenderingStats& stats) { | 63 RenderingStats& stats) { |
39 if (pile_.empty()) { | 64 if (pile_.empty()) { |
40 ResetPile(painter, stats); | 65 ResetPile(painter, stats); |
41 return; | 66 return; |
42 } | 67 } |
43 | 68 |
44 for (Region::Iterator i(invalidation); i.has_rect(); i.next()) | 69 for (Region::Iterator i(invalidation); i.has_rect(); i.next()) |
(...skipping 11 matching lines...) Expand all Loading... | |
56 bool operator()(const scoped_refptr<Picture>& picture) { | 81 bool operator()(const scoped_refptr<Picture>& picture) { |
57 return layer_rect_.Contains(picture->LayerRect()); | 82 return layer_rect_.Contains(picture->LayerRect()); |
58 } | 83 } |
59 gfx::Rect layer_rect_; | 84 gfx::Rect layer_rect_; |
60 }; | 85 }; |
61 | 86 |
62 void PicturePile::InvalidateRect(gfx::Rect invalidation) { | 87 void PicturePile::InvalidateRect(gfx::Rect invalidation) { |
63 if (invalidation.IsEmpty()) | 88 if (invalidation.IsEmpty()) |
64 return; | 89 return; |
65 | 90 |
91 // Inflate all recordings from invalidations with a margin so that when | |
92 // scaled down to at least min_contents_scale, any final pixel touched by an | |
93 // invalidation can be fully rasterized by this picture. | |
94 invalidation.Inset( | |
95 -buffer_pixels_, | |
96 -buffer_pixels_, | |
97 -buffer_pixels_, | |
98 -buffer_pixels_); | |
99 invalidation.Intersect(gfx::Rect(size_)); | |
100 | |
66 std::vector<Pile::iterator> overlaps; | 101 std::vector<Pile::iterator> overlaps; |
67 for (Pile::iterator i = pile_.begin(); i != pile_.end(); ++i) { | 102 for (Pile::iterator i = pile_.begin(); i != pile_.end(); ++i) { |
68 if ((*i)->LayerRect().Contains(invalidation) && !(*i)->HasRecording()) | 103 if ((*i)->LayerRect().Contains(invalidation) && !(*i)->HasRecording()) |
69 return; | 104 return; |
70 if ((*i)->LayerRect().Intersects(invalidation) && i != pile_.begin()) | 105 if ((*i)->LayerRect().Intersects(invalidation) && i != pile_.begin()) |
71 overlaps.push_back(i); | 106 overlaps.push_back(i); |
72 } | 107 } |
73 | 108 |
74 gfx::Rect picture_rect = invalidation; | 109 gfx::Rect picture_rect = invalidation; |
75 if (overlaps.size() >= kMaxOverlapping) { | 110 if (overlaps.size() >= kMaxOverlapping) { |
76 for (size_t j = 0; j < overlaps.size(); j++) | 111 for (size_t j = 0; j < overlaps.size(); j++) |
77 picture_rect = gfx::UnionRects(picture_rect, (*overlaps[j])->LayerRect()); | 112 picture_rect = gfx::UnionRects(picture_rect, (*overlaps[j])->LayerRect()); |
78 } | 113 } |
79 if (picture_rect.size().GetArea() / static_cast<float>(size_.GetArea()) > | 114 if (picture_rect.size().GetArea() / static_cast<float>(size_.GetArea()) > |
80 kResetThreshold) | 115 kResetThreshold) |
81 picture_rect = gfx::Rect(size_); | 116 picture_rect = gfx::Rect(gfx::Rect(size_)); |
danakj
2013/01/05 00:04:58
Yo dawg, I heard you like Rects.
enne (OOO)
2013/01/06 03:57:18
Oops.
| |
82 | 117 |
83 FullyContainedPredicate pred(picture_rect); | 118 FullyContainedPredicate pred(picture_rect); |
84 pile_.erase(std::remove_if(pile_.begin(), pile_.end(), pred), pile_.end()); | 119 pile_.erase(std::remove_if(pile_.begin(), pile_.end(), pred), pile_.end()); |
85 | 120 |
86 pile_.push_back(Picture::Create(picture_rect)); | 121 pile_.push_back(Picture::Create(picture_rect)); |
87 } | 122 } |
88 | 123 |
89 | 124 |
90 void PicturePile::ResetPile(ContentLayerClient* painter, | 125 void PicturePile::ResetPile(ContentLayerClient* painter, |
91 RenderingStats& stats) { | 126 RenderingStats& stats) { |
92 pile_.clear(); | 127 pile_.clear(); |
93 | 128 |
94 scoped_refptr<Picture> base_picture = Picture::Create(gfx::Rect(size_)); | 129 scoped_refptr<Picture> base_picture = Picture::Create(gfx::Rect(size_)); |
95 base_picture->Record(painter, stats); | 130 base_picture->Record(painter, stats); |
96 pile_.push_back(base_picture); | 131 pile_.push_back(base_picture); |
97 } | 132 } |
98 | 133 |
99 void PicturePile::PushPropertiesTo(PicturePileImpl* other) { | 134 void PicturePile::PushPropertiesTo(PicturePileImpl* other) { |
100 other->pile_ = pile_; | 135 other->pile_ = pile_; |
136 other->min_contents_scale_ = min_contents_scale_; | |
101 // Remove all old clones. | 137 // Remove all old clones. |
102 other->clones_.clear(); | 138 other->clones_.clear(); |
103 } | 139 } |
104 | 140 |
105 } // namespace cc | 141 } // namespace cc |
OLD | NEW |