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 { |
| 11 // Maximum number of pictures that can overlap before we collapse them into |
| 12 // a larger one. |
| 13 const int kMaxOverlapping = 2; |
| 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. |
| 16 const float kResetThreshold = 0.7f; |
| 17 } |
| 18 |
10 namespace cc { | 19 namespace cc { |
11 | 20 |
12 PicturePile::PicturePile() { | 21 PicturePile::PicturePile() { |
13 } | 22 } |
14 | 23 |
15 PicturePile::~PicturePile() { | 24 PicturePile::~PicturePile() { |
16 } | 25 } |
17 | 26 |
18 class OutOfBoundsPredicate { | 27 void PicturePile::Resize(gfx::Size size) { |
19 public: | 28 if (size_ == size) |
20 OutOfBoundsPredicate(gfx::Size size) : layer_rect_(gfx::Point(), size) { } | 29 return; |
21 bool operator()(const scoped_refptr<Picture>& picture) { | |
22 return !picture->LayerRect().Intersects(layer_rect_); | |
23 } | |
24 gfx::Rect layer_rect_; | |
25 }; | |
26 | 30 |
27 void PicturePile::Resize(gfx::Size size) { | 31 pile_.clear(); |
28 // Remove pictures that aren't in bounds anymore. | |
29 if (size.width() < size_.width() || size.height() < size_.height()) { | |
30 OutOfBoundsPredicate oob(size); | |
31 pile_.erase(std::remove_if(pile_.begin(), pile_.end(), oob), pile_.end()); | |
32 } | |
33 | |
34 size_ = size; | 32 size_ = size; |
35 } | 33 } |
36 | 34 |
37 void PicturePile::Update( | 35 void PicturePile::Update( |
38 ContentLayerClient* painter, | 36 ContentLayerClient* painter, |
39 const Region&, | 37 const Region& invalidation, |
40 RenderingStats& stats) { | 38 RenderingStats& stats) { |
41 // TODO(enne): Add things to the pile, consolidate if needed, etc... | 39 if (pile_.empty()) { |
42 // TODO(enne): Only re-record invalidated areas. | 40 ResetPile(painter, stats); |
43 // TODO(enne): Also re-record areas that have been newly exposed by resize. | 41 return; |
| 42 } |
44 | 43 |
45 // Always re-record the entire layer into a single picture, just to get | 44 for (Region::Iterator i(invalidation); i.has_rect(); i.next()) |
46 // this class up and running. | 45 InvalidateRect(i.rect()); |
| 46 |
| 47 for (Pile::iterator i = pile_.begin(); i != pile_.end(); ++i) { |
| 48 if (!(*i)->HasRecording()) |
| 49 (*i)->Record(painter, stats); |
| 50 } |
| 51 } |
| 52 |
| 53 class FullyContainedPredicate { |
| 54 public: |
| 55 FullyContainedPredicate(gfx::Rect rect) : layer_rect_(rect) { } |
| 56 bool operator()(const scoped_refptr<Picture>& picture) { |
| 57 return layer_rect_.Contains(picture->LayerRect()); |
| 58 } |
| 59 gfx::Rect layer_rect_; |
| 60 }; |
| 61 |
| 62 void PicturePile::InvalidateRect(gfx::Rect invalidation) { |
| 63 if (invalidation.IsEmpty()) |
| 64 return; |
| 65 |
| 66 std::vector<Pile::iterator> overlaps; |
| 67 for (Pile::iterator i = pile_.begin(); i != pile_.end(); ++i) { |
| 68 if ((*i)->LayerRect().Contains(invalidation) && !(*i)->HasRecording()) |
| 69 return; |
| 70 if ((*i)->LayerRect().Intersects(invalidation) && i != pile_.begin()) |
| 71 overlaps.push_back(i); |
| 72 } |
| 73 |
| 74 gfx::Rect picture_rect = invalidation; |
| 75 if (overlaps.size() >= kMaxOverlapping) { |
| 76 for (size_t j = 0; j < overlaps.size(); j++) |
| 77 picture_rect = gfx::UnionRects(picture_rect, (*overlaps[j])->LayerRect()); |
| 78 } |
| 79 if (picture_rect.size().GetArea() / static_cast<float>(size_.GetArea()) > |
| 80 kResetThreshold) |
| 81 picture_rect = gfx::Rect(size_); |
| 82 |
| 83 FullyContainedPredicate pred(picture_rect); |
| 84 pile_.erase(std::remove_if(pile_.begin(), pile_.end(), pred), pile_.end()); |
| 85 |
| 86 pile_.push_back(Picture::Create(picture_rect)); |
| 87 } |
| 88 |
| 89 |
| 90 void PicturePile::ResetPile(ContentLayerClient* painter, |
| 91 RenderingStats& stats) { |
47 pile_.clear(); | 92 pile_.clear(); |
48 pile_.push_back(Picture::Create()); | 93 |
49 pile_[0]->Record(painter, gfx::Rect(gfx::Point(), size_), stats); | 94 scoped_refptr<Picture> base_picture = Picture::Create(gfx::Rect(size_)); |
| 95 base_picture->Record(painter, stats); |
| 96 pile_.push_back(base_picture); |
50 } | 97 } |
51 | 98 |
52 void PicturePile::PushPropertiesTo(PicturePileImpl* other) { | 99 void PicturePile::PushPropertiesTo(PicturePileImpl* other) { |
53 other->pile_.resize(pile_.size()); | 100 other->pile_ = pile_; |
54 for (size_t i = 0; i < pile_.size(); ++i) | |
55 other->pile_[i] = pile_[i]; | |
56 } | 101 } |
57 | 102 |
58 } // namespace cc | 103 } // namespace cc |
OLD | NEW |