// 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 #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() { } PicturePile::~PicturePile() { } 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: FullyContainedPredicate(gfx::Rect rect) : layer_rect_(rect) { } bool operator()(const scoped_refptr& picture) { return layer_rect_.Contains(picture->LayerRect()); } gfx::Rect layer_rect_; }; void PicturePile::InvalidateRect(gfx::Rect invalidation) { if (invalidation.IsEmpty()) return; std::vector 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(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 base_picture = Picture::Create(gfx::Rect(size_)); base_picture->Record(painter, stats); pile_.push_back(base_picture); } void PicturePile::PushPropertiesTo(PicturePileImpl* other) { other->pile_ = pile_; // Remove all old clones. other->clones_.clear(); } } // namespace cc