Index: cc/picture_pile.cc |
diff --git a/cc/picture_pile.cc b/cc/picture_pile.cc |
index 9a6ac595273599b27899237a8f828321c8d11ad7..1e9109096e4c064e76ca43fe69daffbb85079c35 100644 |
--- a/cc/picture_pile.cc |
+++ b/cc/picture_pile.cc |
@@ -7,6 +7,15 @@ |
#include "cc/picture_pile.h" |
#include "cc/picture_pile_impl.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() { |
@@ -15,44 +24,80 @@ PicturePile::PicturePile() { |
PicturePile::~PicturePile() { |
} |
-class OutOfBoundsPredicate { |
+void PicturePile::Resize(gfx::Size size) { |
+ if (size_ == size) |
+ return; |
+ |
+ pile_.clear(); |
+ size_ = size; |
+} |
+ |
+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: |
- OutOfBoundsPredicate(gfx::Size size) : layer_rect_(gfx::Point(), size) { } |
+ FullyContainedPredicate(gfx::Rect rect) : layer_rect_(rect) { } |
bool operator()(const scoped_refptr<Picture>& picture) { |
- return !picture->LayerRect().Intersects(layer_rect_); |
+ return layer_rect_.Contains(picture->LayerRect()); |
} |
gfx::Rect layer_rect_; |
}; |
-void PicturePile::Resize(gfx::Size size) { |
- // Remove pictures that aren't in bounds anymore. |
- if (size.width() < size_.width() || size.height() < size_.height()) { |
- OutOfBoundsPredicate oob(size); |
- pile_.erase(std::remove_if(pile_.begin(), pile_.end(), oob), pile_.end()); |
+void PicturePile::InvalidateRect(gfx::Rect invalidation) { |
+ if (invalidation.IsEmpty()) |
+ return; |
+ |
+ 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); |
} |
- size_ = size; |
+ 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::Update( |
- ContentLayerClient* painter, |
- const Region&, |
- RenderingStats& stats) { |
- // TODO(enne): Add things to the pile, consolidate if needed, etc... |
- // TODO(enne): Only re-record invalidated areas. |
- // TODO(enne): Also re-record areas that have been newly exposed by resize. |
- // Always re-record the entire layer into a single picture, just to get |
- // this class up and running. |
+void PicturePile::ResetPile(ContentLayerClient* painter, |
+ RenderingStats& stats) { |
pile_.clear(); |
- pile_.push_back(Picture::Create()); |
- pile_[0]->Record(painter, gfx::Rect(gfx::Point(), size_), stats); |
+ |
+ 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) { |
- other->pile_.resize(pile_.size()); |
- for (size_t i = 0; i < pile_.size(); ++i) |
- other->pile_[i] = pile_[i]; |
+ other->pile_ = pile_; |
} |
} // namespace cc |