summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorenne@chromium.org <enne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-01-09 23:54:31 +0000
committerenne@chromium.org <enne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-01-09 23:54:31 +0000
commit166db5c8936232da188fbae0c8b0932f92b1df0f (patch)
treeef2b4c2751d0524f83ca2e81572e0bed722e619e
parentf368a2e7f88cff715ed231b04381543e4eac2fbc (diff)
downloadchromium_src-166db5c8936232da188fbae0c8b0932f92b1df0f.zip
chromium_src-166db5c8936232da188fbae0c8b0932f92b1df0f.tar.gz
chromium_src-166db5c8936232da188fbae0c8b0932f92b1df0f.tar.bz2
cc: Generate tilings at other scales for impl-side painting
This patch adds infrastructure to make it easy for PictureLayerImpl to manage its set of tilings via PictureLayerImpl::ManageTiles(). The main functionality change is to additionally generate a low-res set of tiles (by default 1/8 resolution). Along with generating tilings at different scales, tile priorities now have the correct resolution set on them so that they can be prioritized correctly. There's a few small bugfixes added here as well for correctness, such as making sure that tilings are sorted in the PictureLayerTilingSet from highest to lowest. (This is the order in which tiles will be used.) It also correctly calculates a synthetic contents scale / content bounds for the PictureLayerImpl to support multiple active contents scales. R=nduca@chromium.org BUG=167300 Review URL: https://chromiumcodereview.appspot.com/11704002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@175927 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--cc/layer_tree_host_impl.h2
-rw-r--r--cc/layer_tree_impl.cc4
-rw-r--r--cc/layer_tree_impl.h1
-rw-r--r--cc/layer_tree_settings.cc1
-rw-r--r--cc/layer_tree_settings.h1
-rw-r--r--cc/picture_layer_impl.cc168
-rw-r--r--cc/picture_layer_impl.h7
-rw-r--r--cc/picture_layer_tiling.cc39
-rw-r--r--cc/picture_layer_tiling.h8
-rw-r--r--cc/picture_layer_tiling_set.cc86
-rw-r--r--cc/picture_layer_tiling_set.h20
-rw-r--r--cc/picture_layer_tiling_set_unittest.cc6
-rw-r--r--cc/scoped_ptr_vector.h5
-rw-r--r--cc/tile.h4
14 files changed, 287 insertions, 65 deletions
diff --git a/cc/layer_tree_host_impl.h b/cc/layer_tree_host_impl.h
index 4091d48..d6ba579 100644
--- a/cc/layer_tree_host_impl.h
+++ b/cc/layer_tree_host_impl.h
@@ -304,6 +304,8 @@ public:
skia::RefPtr<SkPicture> capturePicture();
+ bool pinchGestureActive() const { return m_pinchGestureActive; }
+
protected:
LayerTreeHostImpl(const LayerTreeSettings&, LayerTreeHostImplClient*, Proxy*);
void activatePendingTree();
diff --git a/cc/layer_tree_impl.cc b/cc/layer_tree_impl.cc
index 7c2cc4c..805db07 100644
--- a/cc/layer_tree_impl.cc
+++ b/cc/layer_tree_impl.cc
@@ -229,6 +229,10 @@ int LayerTreeImpl::MaxTextureSize() const {
return layer_tree_host_impl_->rendererCapabilities().maxTextureSize;
}
+bool LayerTreeImpl::PinchGestureActive() const {
+ return layer_tree_host_impl_->pinchGestureActive();
+}
+
void LayerTreeImpl::SetNeedsRedraw() {
layer_tree_host_impl_->setNeedsRedraw();
}
diff --git a/cc/layer_tree_impl.h b/cc/layer_tree_impl.h
index 801dde6b..308448b 100644
--- a/cc/layer_tree_impl.h
+++ b/cc/layer_tree_impl.h
@@ -55,6 +55,7 @@ class CC_EXPORT LayerTreeImpl {
LayerImpl* FindActiveTreeLayerById(int id);
LayerImpl* FindPendingTreeLayerById(int id);
int MaxTextureSize() const;
+ bool PinchGestureActive() const;
// Tree specific methods exposed to layer-impl tree.
// ---------------------------------------------------------------------------
diff --git a/cc/layer_tree_settings.cc b/cc/layer_tree_settings.cc
index ece7991..0891f93 100644
--- a/cc/layer_tree_settings.cc
+++ b/cc/layer_tree_settings.cc
@@ -28,6 +28,7 @@ LayerTreeSettings::LayerTreeSettings()
, shouldClearRootRenderPass(true)
, useLinearFadeScrollbarAnimator(false)
, minimumContentsScale(0.0625f)
+ , lowResContentsScaleFactor(0.125f)
, refreshRate(0)
, maxPartialTextureUpdates(std::numeric_limits<size_t>::max())
, numRasterThreads(1)
diff --git a/cc/layer_tree_settings.h b/cc/layer_tree_settings.h
index 84810f7..375cbf6 100644
--- a/cc/layer_tree_settings.h
+++ b/cc/layer_tree_settings.h
@@ -31,6 +31,7 @@ class CC_EXPORT LayerTreeSettings {
bool shouldClearRootRenderPass;
bool useLinearFadeScrollbarAnimator;
float minimumContentsScale;
+ float lowResContentsScaleFactor;
double refreshRate;
size_t maxPartialTextureUpdates;
size_t numRasterThreads;
diff --git a/cc/picture_layer_impl.cc b/cc/picture_layer_impl.cc
index 5a6f111..de06993 100644
--- a/cc/picture_layer_impl.cc
+++ b/cc/picture_layer_impl.cc
@@ -17,6 +17,10 @@
#include "ui/gfx/quad_f.h"
#include "ui/gfx/size_conversions.h"
+namespace {
+const float kMaxScaleRatioDuringPinch = 2.0f;
+}
+
namespace cc {
PictureLayerImpl::PictureLayerImpl(LayerTreeImpl* treeImpl, int id)
@@ -24,6 +28,8 @@ PictureLayerImpl::PictureLayerImpl(LayerTreeImpl* treeImpl, int id)
tilings_(this),
pile_(PicturePileImpl::Create()),
last_update_time_(0),
+ last_content_scale_(0),
+ ideal_contents_scale_(0),
is_mask_(false) {
}
@@ -53,7 +59,8 @@ void PictureLayerImpl::appendQuads(QuadSink& quadSink,
if (showDebugBorders()) {
for (PictureLayerTilingSet::Iterator iter(&tilings_,
contentsScaleX(),
- rect);
+ rect,
+ ideal_contents_scale_);
iter;
++iter) {
SkColor color;
@@ -74,7 +81,14 @@ void PictureLayerImpl::appendQuads(QuadSink& quadSink,
}
}
- for (PictureLayerTilingSet::Iterator iter(&tilings_, contentsScaleX(), rect);
+ // Keep track of the tilings that were used so that tilings that are
+ // unused can be considered for removal.
+ std::vector<PictureLayerTiling*> seen_tilings;
+
+ for (PictureLayerTilingSet::Iterator iter(&tilings_,
+ contentsScaleX(),
+ rect,
+ ideal_contents_scale_);
iter;
++iter) {
ResourceProvider::ResourceId resource = 0;
@@ -122,7 +136,15 @@ void PictureLayerImpl::appendQuads(QuadSink& quadSink,
outside_right_edge && useAA,
outside_bottom_edge && useAA);
quadSink.append(quad.PassAs<DrawQuad>(), appendQuadsData);
+
+ if (!seen_tilings.size() || seen_tilings.back() != iter.CurrentTiling())
+ seen_tilings.push_back(iter.CurrentTiling());
}
+
+ // During a pinch, a user could zoom in and out, so throwing away a tiling may
+ // be premature.
+ if (!layerTreeImpl()->PinchGestureActive())
+ CleanUpUnusedTilings(seen_tilings);
}
void PictureLayerImpl::dumpLayerProperties(std::string*, int indent) const {
@@ -137,16 +159,15 @@ void PictureLayerImpl::didUpdateTransforms() {
double time_delta = 0;
if (last_update_time_ != 0 && last_bounds_ == bounds() &&
last_content_bounds_ == contentBounds() &&
- last_content_scale_x_ == contentsScaleX() &&
- last_content_scale_y_ == contentsScaleY()) {
+ last_content_scale_ == contentsScaleX()) {
time_delta = current_time - last_update_time_;
}
WhichTree tree = layerTreeImpl()->IsActiveTree() ? ACTIVE_TREE : PENDING_TREE;
tilings_.UpdateTilePriorities(
tree,
layerTreeImpl()->device_viewport_size(),
+ last_content_scale_,
contentsScaleX(),
- contentsScaleY(),
last_screen_space_transform_,
current_screen_space_transform,
time_delta);
@@ -155,8 +176,7 @@ void PictureLayerImpl::didUpdateTransforms() {
last_update_time_ = current_time;
last_bounds_ = bounds();
last_content_bounds_ = contentBounds();
- last_content_scale_x_ = contentsScaleX();
- last_content_scale_y_ = contentsScaleY();
+ last_content_scale_ = contentsScaleX();
}
void PictureLayerImpl::calculateContentsScale(
@@ -170,9 +190,9 @@ void PictureLayerImpl::calculateContentsScale(
}
float min_contents_scale = layerTreeImpl()->settings().minimumContentsScale;
- ideal_contents_scale = std::max(ideal_contents_scale, min_contents_scale);
+ ideal_contents_scale_ = std::max(ideal_contents_scale, min_contents_scale);
- ManageTilings(ideal_contents_scale);
+ ManageTilings(ideal_contents_scale_);
// The content scale and bounds for a PictureLayerImpl is somewhat fictitious.
// There are (usually) several tilings at different scales. However, the
@@ -237,13 +257,16 @@ void PictureLayerImpl::SetIsMask(bool is_mask) {
if (is_mask_ == is_mask)
return;
is_mask_ = is_mask;
- tilings_.Reset();
+ tilings_.RemoveAllTiles();
}
ResourceProvider::ResourceId PictureLayerImpl::contentsResourceId() const {
gfx::Rect content_rect(gfx::Point(), contentBounds());
float scale = contentsScaleX();
- for (PictureLayerTilingSet::Iterator iter(&tilings_, scale, content_rect);
+ for (PictureLayerTilingSet::Iterator iter(&tilings_,
+ scale,
+ content_rect,
+ ideal_contents_scale_);
iter;
++iter) {
// Mask resource not ready yet.
@@ -257,25 +280,26 @@ ResourceProvider::ResourceId PictureLayerImpl::contentsResourceId() const {
return 0;
}
-void PictureLayerImpl::AddTiling(float contents_scale, gfx::Size tile_size) {
+PictureLayerTiling* PictureLayerImpl::AddTiling(float contents_scale) {
if (contents_scale < layerTreeImpl()->settings().minimumContentsScale)
- return;
+ return NULL;
- const PictureLayerTiling* tiling = tilings_.AddTiling(
+ PictureLayerTiling* tiling = tilings_.AddTiling(
contents_scale,
- tile_size);
+ TileSize());
// If a new tiling is created on the active tree, sync it to the pending tree
// so that it can share the same tiles.
if (layerTreeImpl()->IsPendingTree())
- return;
+ return tiling;
PictureLayerImpl* pending_twin = static_cast<PictureLayerImpl*>(
layerTreeImpl()->FindPendingTreeLayerById(id()));
if (!pending_twin)
- return;
+ return tiling;
DCHECK_EQ(id(), pending_twin->id());
pending_twin->SyncTiling(tiling);
+ return tiling;
}
gfx::Size PictureLayerImpl::TileSize() const {
@@ -289,18 +313,110 @@ gfx::Size PictureLayerImpl::TileSize() const {
return layerTreeImpl()->settings().defaultTileSize;
}
+namespace {
+
+inline float PositiveRatio(float float1, float float2) {
+ DCHECK(float1 > 0);
+ DCHECK(float2 > 0);
+ return float1 > float2 ? float1 / float2 : float2 / float1;
+}
+
+inline bool IsCloserToThan(
+ PictureLayerTiling* layer1,
+ PictureLayerTiling* layer2,
+ float contents_scale) {
+ // Absolute value for ratios.
+ float ratio1 = PositiveRatio(layer1->contents_scale(), contents_scale);
+ float ratio2 = PositiveRatio(layer2->contents_scale(), contents_scale);
+ return ratio1 < ratio2;
+}
+
+} // namespace
+
void PictureLayerImpl::ManageTilings(float ideal_contents_scale) {
- if (drawsContent()) {
- // TODO(enne): Add tilings during pinch zoom
- // TODO(enne): Consider culling old tilings after pinch finishes.
- if (!tilings_.num_tilings()) {
- AddTiling(ideal_contents_scale, TileSize());
- // TODO(enne): Add a low-res tiling as well.
+ DCHECK(ideal_contents_scale);
+ float low_res_factor = layerTreeImpl()->settings().lowResContentsScaleFactor;
+ float low_res_contents_scale = ideal_contents_scale * low_res_factor;
+
+ // Remove any tilings from the pending tree that don't exactly match the
+ // contents scale. The pending tree should always come in crisp. However,
+ // don't do this during a pinch, to avoid throwing away a tiling that should
+ // have been kept.
+ if (layerTreeImpl()->IsPendingTree() &&
+ !layerTreeImpl()->PinchGestureActive()) {
+ std::vector<PictureLayerTiling*> remove_list;
+ for (size_t i = 0; i < tilings_.num_tilings(); ++i) {
+ PictureLayerTiling* tiling = tilings_.tiling_at(i);
+ if (tiling->contents_scale() == ideal_contents_scale)
+ continue;
+ if (tiling->contents_scale() == low_res_contents_scale)
+ continue;
+ remove_list.push_back(tiling);
}
- } else {
- // TODO(enne): This should be unnecessary once there are two trees.
- tilings_.Reset();
+
+ for (size_t i = 0; i < remove_list.size(); ++i)
+ tilings_.Remove(remove_list[i]);
}
+
+ // Find existing tilings closest to ideal high / low res.
+ PictureLayerTiling* high_res = NULL;
+ PictureLayerTiling* low_res = NULL;
+ for (size_t i = 0; i < tilings_.num_tilings(); ++i) {
+ PictureLayerTiling* tiling = tilings_.tiling_at(i);
+ if (!high_res || IsCloserToThan(tiling, high_res, ideal_contents_scale))
+ high_res = tiling;
+ if (!low_res || IsCloserToThan(tiling, low_res, low_res_contents_scale))
+ low_res = tiling;
+
+ // Reset all tilings to non-ideal until the end of this function.
+ tiling->set_resolution(NON_IDEAL_RESOLUTION);
+ }
+
+ // The active tree always has calcDrawProperties called on it first, and
+ // any tilings added to the active tree will be synced to the pending tree.
+ // Therefore, only add tilings to the active tree.
+ if (layerTreeImpl()->IsActiveTree()) {
+ if (layerTreeImpl()->PinchGestureActive() && high_res) {
+ // If zooming out, if only available high-res tiling is very high
+ // resolution, create additional tilings closer to the ideal.
+ // When zooming in, add some additional tilings so that content
+ // "crisps up" prior to releasing pinch.
+ float ratio = PositiveRatio(
+ high_res->contents_scale(),
+ ideal_contents_scale);
+ if (ratio >= kMaxScaleRatioDuringPinch)
+ high_res = AddTiling(ideal_contents_scale);
+ } else {
+ // When not pinching or if no tilings, add exact contents scales.
+ if (!high_res || high_res->contents_scale() != ideal_contents_scale)
+ high_res = AddTiling(ideal_contents_scale);
+ if (!low_res || low_res->contents_scale() != low_res_contents_scale)
+ low_res = AddTiling(low_res_contents_scale);
+ }
+ }
+
+ if (high_res)
+ high_res->set_resolution(HIGH_RESOLUTION);
+ if (low_res && low_res != high_res)
+ low_res->set_resolution(LOW_RESOLUTION);
+}
+
+void PictureLayerImpl::CleanUpUnusedTilings(
+ std::vector<PictureLayerTiling*> used_tilings) {
+ std::vector<PictureLayerTiling*> to_remove;
+
+ for (size_t i = 0; i < tilings_.num_tilings(); ++i) {
+ PictureLayerTiling* tiling = tilings_.tiling_at(i);
+ // Don't remove the current high or low res tilinig.
+ if (tiling->resolution() != NON_IDEAL_RESOLUTION)
+ continue;
+ if (std::find(used_tilings.begin(), used_tilings.end(), tiling) ==
+ used_tilings.end())
+ to_remove.push_back(tiling);
+ }
+
+ for (size_t i = 0; i < to_remove.size(); ++i)
+ tilings_.Remove(to_remove[i]);
}
} // namespace cc
diff --git a/cc/picture_layer_impl.h b/cc/picture_layer_impl.h
index 94c1ac3..1712b44 100644
--- a/cc/picture_layer_impl.h
+++ b/cc/picture_layer_impl.h
@@ -53,10 +53,11 @@ public:
protected:
PictureLayerImpl(LayerTreeImpl* treeImpl, int id);
- void AddTiling(float contents_scale, gfx::Size tile_size);
+ PictureLayerTiling* AddTiling(float contents_scale);
void SyncFromActiveLayer(const PictureLayerImpl* other);
gfx::Size TileSize() const;
void ManageTilings(float ideal_contents_scale);
+ void CleanUpUnusedTilings(std::vector<PictureLayerTiling*> used_tilings);
PictureLayerTilingSet tilings_;
scoped_refptr<PicturePileImpl> pile_;
@@ -66,8 +67,8 @@ protected:
double last_update_time_;
gfx::Size last_bounds_;
gfx::Size last_content_bounds_;
- float last_content_scale_x_;
- float last_content_scale_y_;
+ float last_content_scale_;
+ float ideal_contents_scale_;
bool is_mask_;
friend class PictureLayer;
diff --git a/cc/picture_layer_tiling.cc b/cc/picture_layer_tiling.cc
index 7ea16fd..43d52c7 100644
--- a/cc/picture_layer_tiling.cc
+++ b/cc/picture_layer_tiling.cc
@@ -24,7 +24,8 @@ PictureLayerTiling::PictureLayerTiling(float contents_scale,
gfx::Size tile_size)
: client_(NULL),
contents_scale_(contents_scale),
- tiling_data_(tile_size, gfx::Size(), true) {
+ tiling_data_(tile_size, gfx::Size(), true),
+ resolution_(NON_IDEAL_RESOLUTION) {
}
PictureLayerTiling::~PictureLayerTiling() {
@@ -60,12 +61,6 @@ void PictureLayerTiling::CreateTile(int i, int j) {
TileMapKey key(i, j);
DCHECK(!tiles_[key]);
tiles_[key] = client_->CreateTile(this, tile_rect);
-
- // TODO(enne): Remove this when we start setting priorities correctly.
- TilePriority priority;
- priority.resolution = HIGH_RESOLUTION;
- priority.time_to_visible_in_seconds = 1000;
- tiles_[key]->set_priority(ACTIVE_TREE, priority);
}
Region PictureLayerTiling::OpaqueRegionInContentRect(
@@ -271,8 +266,8 @@ gfx::Size PictureLayerTiling::Iterator::texture_size() const {
void PictureLayerTiling::UpdateTilePriorities(
WhichTree tree,
const gfx::Size& device_viewport,
- float layer_content_scale_x,
- float layer_content_scale_y,
+ float last_layer_contents_scale,
+ float current_layer_contents_scale,
const gfx::Transform& last_screen_transform,
const gfx::Transform& current_screen_transform,
double time_delta) {
@@ -287,6 +282,7 @@ void PictureLayerTiling::UpdateTilePriorities(
for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) {
TileMapKey key = it->first;
TilePriority priority;
+ priority.resolution = resolution_;
if (key.first > right || key.second > bottom) {
priority.distance_to_visible_in_pixels = std::numeric_limits<int>::max();
priority.time_to_visible_in_seconds =
@@ -296,22 +292,25 @@ void PictureLayerTiling::UpdateTilePriorities(
}
gfx::Rect tile_bound = tiling_data_.TileBounds(key.first, key.second);
- gfx::RectF layer_content_rect = gfx::ScaleRect(
+ gfx::RectF current_layer_content_rect = gfx::ScaleRect(
+ tile_bound,
+ current_layer_contents_scale / contents_scale_,
+ current_layer_contents_scale / contents_scale_);
+ gfx::RectF current_screen_rect = MathUtil::mapClippedRect(
+ current_screen_transform, current_layer_content_rect);
+ gfx::RectF last_layer_content_rect = gfx::ScaleRect(
tile_bound,
- layer_content_scale_x / contents_scale_,
- layer_content_scale_y / contents_scale_);
- gfx::RectF screen_rect = MathUtil::mapClippedRect(
- current_screen_transform, layer_content_rect);
- gfx::RectF previous_rect = MathUtil::mapClippedRect(
- last_screen_transform, layer_content_rect);
-
- priority.resolution = HIGH_RESOLUTION;
+ last_layer_contents_scale / contents_scale_,
+ last_layer_contents_scale / contents_scale_);
+ gfx::RectF last_screen_rect = MathUtil::mapClippedRect(
+ last_screen_transform, last_layer_content_rect);
+
priority.time_to_visible_in_seconds =
TilePriority::TimeForBoundsToIntersect(
- previous_rect, screen_rect, time_delta, view_rect);
+ last_screen_rect, current_screen_rect, time_delta, view_rect);
priority.distance_to_visible_in_pixels =
- TilePriority::manhattanDistance(screen_rect, view_rect);
+ TilePriority::manhattanDistance(current_screen_rect, view_rect);
it->second->set_priority(tree, priority);
}
}
diff --git a/cc/picture_layer_tiling.h b/cc/picture_layer_tiling.h
index b6c7b7d..38ef4c6 100644
--- a/cc/picture_layer_tiling.h
+++ b/cc/picture_layer_tiling.h
@@ -12,6 +12,7 @@
#include "cc/hash_pair.h"
#include "cc/region.h"
#include "cc/tile.h"
+#include "cc/tile_priority.h"
#include "cc/tiling_data.h"
#include "ui/gfx/rect.h"
@@ -38,6 +39,8 @@ class CC_EXPORT PictureLayerTiling {
void Invalidate(const Region& layer_invalidation);
void SetClient(PictureLayerTilingClient* client);
+ void set_resolution(TileResolution resolution) { resolution_ = resolution; }
+ TileResolution resolution() const { return resolution_; }
gfx::Rect ContentRect() const;
float contents_scale() const { return contents_scale_; }
@@ -89,8 +92,8 @@ class CC_EXPORT PictureLayerTiling {
void UpdateTilePriorities(
WhichTree tree,
const gfx::Size& device_viewport,
- float layer_content_scale_x,
- float layer_content_scale_y,
+ float last_contents_scale,
+ float current_contents_scale,
const gfx::Transform& last_screen_transform,
const gfx::Transform& current_screen_transform,
double time_delta);
@@ -108,6 +111,7 @@ class CC_EXPORT PictureLayerTiling {
gfx::Size layer_bounds_;
TileMap tiles_;
TilingData tiling_data_;
+ TileResolution resolution_;
friend class Iterator;
};
diff --git a/cc/picture_layer_tiling_set.cc b/cc/picture_layer_tiling_set.cc
index e4bbd57..3ee9107 100644
--- a/cc/picture_layer_tiling_set.cc
+++ b/cc/picture_layer_tiling_set.cc
@@ -6,6 +6,18 @@
namespace cc {
+namespace {
+
+class LargestToSmallestScaleFunctor {
+ public:
+ bool operator() (PictureLayerTiling* left, PictureLayerTiling* right) {
+ return left->contents_scale() > right->contents_scale();
+ }
+};
+
+} // namespace
+
+
PictureLayerTilingSet::PictureLayerTilingSet(
PictureLayerTilingClient * client)
: client_(client) {
@@ -37,6 +49,8 @@ void PictureLayerTilingSet::Clone(
tilings_.push_back(tiling->Clone());
tilings_.back()->SetClient(client_);
tilings_.back()->Invalidate(invalidation);
+
+ tilings_.sort(LargestToSmallestScaleFunctor());
}
void PictureLayerTilingSet::SetLayerBounds(gfx::Size layer_bounds) {
@@ -51,27 +65,57 @@ gfx::Size PictureLayerTilingSet::LayerBounds() const {
return layer_bounds_;
}
-const PictureLayerTiling* PictureLayerTilingSet::AddTiling(
+PictureLayerTiling* PictureLayerTilingSet::AddTiling(
float contents_scale,
gfx::Size tile_size) {
tilings_.push_back(PictureLayerTiling::Create(contents_scale, tile_size));
- tilings_.back()->SetClient(client_);
- tilings_.back()->SetLayerBounds(layer_bounds_);
- return tilings_.back();
+ PictureLayerTiling* appended = tilings_.back();
+ appended->SetClient(client_);
+ appended->SetLayerBounds(layer_bounds_);
+
+ tilings_.sort(LargestToSmallestScaleFunctor());
+ return appended;
+}
+
+void PictureLayerTilingSet::RemoveAllTilings() {
+ tilings_.clear();
}
-void PictureLayerTilingSet::Reset() {
+void PictureLayerTilingSet::Remove(PictureLayerTiling* tiling) {
+ ScopedPtrVector<PictureLayerTiling>::iterator iter =
+ std::find(tilings_.begin(), tilings_.end(), tiling);
+ if (iter == tilings_.end())
+ return;
+ tilings_.erase(iter);
+}
+
+void PictureLayerTilingSet::RemoveAllTiles() {
for (size_t i = 0; i < tilings_.size(); ++i)
tilings_[i]->Reset();
}
-PictureLayerTilingSet::Iterator::Iterator(const PictureLayerTilingSet* set,
- float contents_scale,
- gfx::Rect content_rect)
+PictureLayerTilingSet::Iterator::Iterator(
+ const PictureLayerTilingSet* set,
+ float contents_scale,
+ gfx::Rect content_rect,
+ float ideal_contents_scale)
: set_(set),
contents_scale_(contents_scale),
+ ideal_contents_scale_(ideal_contents_scale),
current_tiling_(-1) {
missing_region_.Union(content_rect);
+
+ for (ideal_tiling_ = 0;
+ static_cast<size_t>(ideal_tiling_) < set_->tilings_.size();
+ ++ideal_tiling_) {
+ PictureLayerTiling* tiling = set_->tilings_[ideal_tiling_];
+ if (tiling->contents_scale() < ideal_contents_scale_) {
+ if (ideal_tiling_ > 0)
+ ideal_tiling_--;
+ break;
+ }
+ }
+
++(*this);
}
@@ -111,6 +155,30 @@ Tile* PictureLayerTilingSet::Iterator::operator*() const {
return *tiling_iter_;
}
+PictureLayerTiling* PictureLayerTilingSet::Iterator::CurrentTiling() {
+ if (current_tiling_ < 0)
+ return NULL;
+ if (static_cast<size_t>(current_tiling_) >= set_->tilings_.size())
+ return NULL;
+ return set_->tilings_[current_tiling_];
+}
+
+int PictureLayerTilingSet::Iterator::NextTiling() const {
+ // Order returned by this method is:
+ // 1. Ideal tiling index
+ // 2. Tiling index < Ideal in decreasing order (higher res than ideal)
+ // 3. Tiling index > Ideal in increasing order (lower res than ideal)
+ // 4. Tiling index > tilings.size() (invalid index)
+ if (current_tiling_ < 0)
+ return ideal_tiling_;
+ else if (current_tiling_ > ideal_tiling_)
+ return current_tiling_ + 1;
+ else if (current_tiling_)
+ return current_tiling_ - 1;
+ else
+ return ideal_tiling_ + 1;
+}
+
PictureLayerTilingSet::Iterator& PictureLayerTilingSet::Iterator::operator++() {
bool first_time = current_tiling_ < 0;
@@ -133,7 +201,7 @@ PictureLayerTilingSet::Iterator& PictureLayerTilingSet::Iterator::operator++() {
// tiling and set up to iterate through all of the remaining holes.
// This will also happen the first time through the loop.
if (!region_iter_.has_rect()) {
- current_tiling_++;
+ current_tiling_ = NextTiling();
current_region_.Swap(missing_region_);
missing_region_.Clear();
region_iter_ = Region::Iterator(current_region_);
diff --git a/cc/picture_layer_tiling_set.h b/cc/picture_layer_tiling_set.h
index 383884e..72b583e 100644
--- a/cc/picture_layer_tiling_set.h
+++ b/cc/picture_layer_tiling_set.h
@@ -26,13 +26,20 @@ class CC_EXPORT PictureLayerTilingSet {
void SetLayerBounds(gfx::Size layer_bounds);
gfx::Size LayerBounds() const;
- const PictureLayerTiling* AddTiling(
+ PictureLayerTiling* AddTiling(
float contents_scale,
gfx::Size tile_size);
size_t num_tilings() const { return tilings_.size(); }
PictureLayerTiling* tiling_at(size_t idx) { return tilings_[idx]; }
- void Reset();
+ // Remove all tilings.
+ void RemoveAllTilings();
+
+ // Remove one tiling.
+ void Remove(PictureLayerTiling* tiling);
+
+ // Remove all tiles; keep all tilings.
+ void RemoveAllTiles();
void UpdateTilePriorities(
WhichTree tree,
@@ -53,7 +60,8 @@ class CC_EXPORT PictureLayerTilingSet {
Iterator(
const PictureLayerTilingSet* set,
float contents_scale,
- gfx::Rect rect);
+ gfx::Rect content_rect,
+ float ideal_contents_scale);
~Iterator();
// Visible rect (no borders), always in the space of rect,
@@ -70,11 +78,17 @@ class CC_EXPORT PictureLayerTilingSet {
Iterator& operator++();
operator bool() const;
+ PictureLayerTiling* CurrentTiling();
+
private:
+ int NextTiling() const;
+
const PictureLayerTilingSet* set_;
float contents_scale_;
+ float ideal_contents_scale_;
PictureLayerTiling::Iterator tiling_iter_;
int current_tiling_;
+ int ideal_tiling_;
Region current_region_;
Region missing_region_;
diff --git a/cc/picture_layer_tiling_set_unittest.cc b/cc/picture_layer_tiling_set_unittest.cc
index 33a2f11..cbc9449 100644
--- a/cc/picture_layer_tiling_set_unittest.cc
+++ b/cc/picture_layer_tiling_set_unittest.cc
@@ -29,7 +29,11 @@ TEST(PictureLayerTilingSetTest, NoResources) {
gfx::Rect content_rect(gfx::Point(), content_bounds);
Region remaining(content_rect);
- PictureLayerTilingSet::Iterator iter(&set, contents_scale, content_rect);
+ PictureLayerTilingSet::Iterator iter(
+ &set,
+ contents_scale,
+ content_rect,
+ contents_scale);
for (; iter; ++iter) {
gfx::Rect geometry_rect = iter.geometry_rect();
EXPECT_TRUE(content_rect.Contains(geometry_rect));
diff --git a/cc/scoped_ptr_vector.h b/cc/scoped_ptr_vector.h
index 2923f46..71e3eb6 100644
--- a/cc/scoped_ptr_vector.h
+++ b/cc/scoped_ptr_vector.h
@@ -140,6 +140,11 @@ class ScopedPtrVector {
std::swap(*writable_a, *writable_b);
}
+ template<class Compare>
+ inline void sort(Compare comp) {
+ std::sort(data_.begin(), data_.end(), comp);
+ }
+
iterator begin() { return static_cast<iterator>(data_.begin()); }
const_iterator begin() const { return data_.begin(); }
iterator end() { return static_cast<iterator>(data_.end()); }
diff --git a/cc/tile.h b/cc/tile.h
index 51c61b7b..7d41e6a 100644
--- a/cc/tile.h
+++ b/cc/tile.h
@@ -51,6 +51,9 @@ class CC_EXPORT Tile : public base::RefCounted<Tile> {
bool contents_swizzled() const { return managed_state_.contents_swizzled; }
+ float contents_scale() const { return contents_scale_; }
+ gfx::Rect content_rect() const { return content_rect_; }
+
private:
// Methods called by by tile manager.
friend class TileManager;
@@ -58,7 +61,6 @@ class CC_EXPORT Tile : public base::RefCounted<Tile> {
ManagedTileState& managed_state() { return managed_state_; }
const ManagedTileState& managed_state() const { return managed_state_; }
size_t bytes_consumed_if_allocated() const;
- float contents_scale() const { return contents_scale_; }
// Normal private methods.
friend class base::RefCounted<Tile>;