blob: eab92c66e39ab46a072adca036e55fcfc5a9f8fe [file] [log] [blame]
// 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"
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>& picture) {
return layer_rect_.Contains(picture->LayerRect());
}
gfx::Rect layer_rect_;
};
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);
}
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) {
other->pile_ = pile_;
// Remove all old clones.
other->clones_.clear();
}
} // namespace cc