summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordanakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-02 04:26:48 +0000
committerdanakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-02 04:26:48 +0000
commit8bc574c57115e9ffd0169f33131c0865997dcb35 (patch)
tree80ba5b6eac129604de092c2ac2358c1777fed3b4
parent0a703911ec7c81384bd52e8e1e5ac4ce012f6f5d (diff)
downloadchromium_src-8bc574c57115e9ffd0169f33131c0865997dcb35.zip
chromium_src-8bc574c57115e9ffd0169f33131c0865997dcb35.tar.gz
chromium_src-8bc574c57115e9ffd0169f33131c0865997dcb35.tar.bz2
cc: Allow non-ideal resolutions to activate the pending tree.
TODO(danakj): Rewrite this description. BUG=172784,173236 NOTRY=true Review URL: https://chromiumcodereview.appspot.com/12087043 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@180244 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--cc/picture_layer_impl.cc321
-rw-r--r--cc/picture_layer_impl.h17
-rw-r--r--cc/picture_layer_impl_unittest.cc234
3 files changed, 465 insertions, 107 deletions
diff --git a/cc/picture_layer_impl.cc b/cc/picture_layer_impl.cc
index 4cba5bd..b7411e8 100644
--- a/cc/picture_layer_impl.cc
+++ b/cc/picture_layer_impl.cc
@@ -29,7 +29,14 @@ PictureLayerImpl::PictureLayerImpl(LayerTreeImpl* treeImpl, int id)
pile_(PicturePileImpl::Create()),
last_content_scale_(0),
ideal_contents_scale_(0),
- is_mask_(false) {
+ is_mask_(false),
+ ideal_page_scale_(0.f),
+ ideal_device_scale_(0.f),
+ ideal_source_scale_(0.f),
+ raster_page_scale_(0.f),
+ raster_device_scale_(0.f),
+ raster_source_scale_(0.f),
+ raster_source_scale_was_animating_(false) {
}
PictureLayerImpl::~PictureLayerImpl() {
@@ -191,7 +198,7 @@ void PictureLayerImpl::appendQuads(QuadSink& quadSink,
drawTransformIsAnimating() ||
screenSpaceTransformIsAnimating();
if (!is_animating)
- CleanUpUnusedTilings(seen_tilings);
+ CleanUpTilingsOnActiveLayer(seen_tilings);
}
void PictureLayerImpl::dumpLayerProperties(std::string*, int indent) const {
@@ -257,9 +264,22 @@ void PictureLayerImpl::calculateContentsScale(
}
float min_contents_scale = layerTreeImpl()->settings().minimumContentsScale;
+ float min_page_scale = layerTreeImpl()->min_page_scale_factor();
+ float min_device_scale = 1.f;
+ float min_source_scale =
+ min_contents_scale / min_page_scale / min_device_scale;
+
+ float ideal_page_scale = layerTreeImpl()->total_page_scale_factor();
+ float ideal_device_scale = layerTreeImpl()->device_scale_factor();
+ float ideal_source_scale =
+ ideal_contents_scale / ideal_page_scale / ideal_device_scale;
+
ideal_contents_scale_ = std::max(ideal_contents_scale, min_contents_scale);
+ ideal_page_scale_ = ideal_page_scale;
+ ideal_device_scale_ = ideal_device_scale;
+ ideal_source_scale_ = std::max(ideal_source_scale, min_source_scale);
- ManageTilings(ideal_contents_scale_);
+ ManageTilings();
// The content scale and bounds for a PictureLayerImpl is somewhat fictitious.
// There are (usually) several tilings at different scales. However, the
@@ -313,11 +333,8 @@ void PictureLayerImpl::SyncFromActiveLayer() {
// If there is an active tree version of this layer, get a copy of its
// tiles. This needs to be done last, after setting invalidation and the
// pile.
- PictureLayerImpl* active_twin = static_cast<PictureLayerImpl*>(
- layerTreeImpl()->FindActiveTreeLayerById(id()));
- if (!active_twin)
- return;
- SyncFromActiveLayer(active_twin);
+ if (PictureLayerImpl* active_twin = ActiveTwin())
+ SyncFromActiveLayer(active_twin);
}
void PictureLayerImpl::SyncFromActiveLayer(const PictureLayerImpl* other) {
@@ -377,63 +394,88 @@ ResourceProvider::ResourceId PictureLayerImpl::contentsResourceId() const {
}
bool PictureLayerImpl::areVisibleResourcesReady() const {
+ DCHECK(ideal_contents_scale_);
+
const gfx::Rect& rect = visibleContentRect();
+ float raster_contents_scale =
+ raster_page_scale_ *
+ raster_device_scale_ *
+ raster_source_scale_;
+
+ float min_acceptable_scale =
+ std::min(raster_contents_scale, ideal_contents_scale_);
+
+ if (layerTreeImpl()->IsPendingTree()) {
+ if (PictureLayerImpl* twin = ActiveTwin()) {
+ float twin_raster_contents_scale =
+ twin->raster_page_scale_ *
+ twin->raster_device_scale_ *
+ twin->raster_source_scale_;
+
+ min_acceptable_scale = std::min(
+ min_acceptable_scale,
+ std::min(twin->ideal_contents_scale_, twin_raster_contents_scale));
+ }
+ }
+
+ Region missing_region = rect;
for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
- const PictureLayerTiling* tiling = tilings_->tiling_at(i);
+ PictureLayerTiling* tiling = tilings_->tiling_at(i);
- // Ignore non-high resolution tilings.
- if (tiling->resolution() != HIGH_RESOLUTION)
+ if (tiling->contents_scale() < min_acceptable_scale)
continue;
for (PictureLayerTiling::Iterator iter(tiling,
- tiling->contents_scale(),
+ contentsScaleX(),
rect);
iter;
++iter) {
// A null tile (i.e. no recording) is considered "ready".
- if (*iter && !iter->GetResourceId())
- return false;
+ if (!*iter || iter->GetResourceId())
+ missing_region.Subtract(iter.geometry_rect());
}
- return true;
}
- return false;
+
+ return missing_region.IsEmpty();
}
PictureLayerTiling* PictureLayerImpl::AddTiling(float contents_scale) {
- if (contents_scale < layerTreeImpl()->settings().minimumContentsScale)
- return NULL;
-
- const Region& recorded = pile_->recorded_region();
- if (recorded.IsEmpty())
- return NULL;
+ DCHECK(contents_scale >= layerTreeImpl()->settings().minimumContentsScale);
PictureLayerTiling* tiling = tilings_->AddTiling(
contents_scale,
TileSize());
+ const Region& recorded = pile_->recorded_region();
+ DCHECK(!recorded.IsEmpty());
+
for (Region::Iterator iter(recorded); iter.has_rect(); iter.next())
tiling->CreateTilesFromLayerRect(iter.rect());
- PictureLayerImpl* twin;
- const Region* pending_layer_invalidation = NULL;
- if (layerTreeImpl()->IsPendingTree()) {
- twin = static_cast<PictureLayerImpl*>(
- layerTreeImpl()->FindActiveTreeLayerById(id()));
- pending_layer_invalidation = &invalidation_;
- } else {
- twin = static_cast<PictureLayerImpl*>(
- layerTreeImpl()->FindPendingTreeLayerById(id()));
- pending_layer_invalidation = &twin->invalidation_;
- }
-
+ PictureLayerImpl* twin =
+ layerTreeImpl()->IsPendingTree() ? ActiveTwin() : PendingTwin();
if (!twin)
return tiling;
- DCHECK_EQ(id(), twin->id());
- twin->SyncTiling(tiling, *pending_layer_invalidation);
+
+ if (layerTreeImpl()->IsPendingTree())
+ twin->SyncTiling(tiling, invalidation_);
+ else
+ twin->SyncTiling(tiling, twin->invalidation_);
+
return tiling;
}
+void PictureLayerImpl::RemoveTiling(float contents_scale) {
+ for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
+ PictureLayerTiling* tiling = tilings_->tiling_at(i);
+ if (tiling->contents_scale() == contents_scale) {
+ tilings_->Remove(tiling);
+ break;
+ }
+ }
+}
+
gfx::Size PictureLayerImpl::TileSize() const {
if (is_mask_) {
int max_size = layerTreeImpl()->MaxTextureSize();
@@ -465,86 +507,92 @@ inline bool IsCloserToThan(
} // namespace
-void PictureLayerImpl::ManageTilings(float ideal_contents_scale) {
- DCHECK(ideal_contents_scale);
+void PictureLayerImpl::ManageTilings() {
+ DCHECK(ideal_contents_scale_);
+ DCHECK(ideal_page_scale_);
+ DCHECK(ideal_device_scale_);
+ DCHECK(ideal_source_scale_);
+
+ if (pile_->recorded_region().IsEmpty())
+ return;
+
float low_res_factor = layerTreeImpl()->settings().lowResContentsScaleFactor;
- float low_res_contents_scale = ideal_contents_scale * low_res_factor;
- bool is_animating = drawTransformIsAnimating() ||
+
+ bool is_active_layer = layerTreeImpl()->IsActiveTree();
+ bool is_pinching = layerTreeImpl()->PinchGestureActive();
+ bool is_animating =
+ drawTransformIsAnimating() ||
screenSpaceTransformIsAnimating();
- // 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() && !is_animating) {
- 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);
- }
+ bool change_target_tiling = false;
+
+ if (!raster_page_scale_ || !raster_device_scale_ || !raster_source_scale_)
+ change_target_tiling = true;
+
+ // TODO(danakj): Adjust raster_source_scale_ closer to ideal_source_scale_ at
+ // a throttled rate. Possibly make use of invalidation_.IsEmpty() on pending
+ // tree. This will allow CSS scale changes to get re-rastered at an
+ // appropriate rate.
- for (size_t i = 0; i < remove_list.size(); ++i)
- tilings_->Remove(remove_list[i]);
+ if (is_active_layer) {
+ if (raster_source_scale_was_animating_ && !is_animating)
+ change_target_tiling = true;
+ raster_source_scale_was_animating_ = is_animating;
}
+ if (is_active_layer && is_pinching) {
+ // If the page scale diverges too far during pinch, change raster target to
+ // the current page scale.
+ float ratio = PositiveRatio(ideal_page_scale_, raster_page_scale_);
+ if (ratio >= kMaxScaleRatioDuringPinch)
+ change_target_tiling = true;
+ }
+
+ if (!is_pinching) {
+ // When not pinching, match the ideal page scale factor.
+ if (raster_page_scale_ != ideal_page_scale_)
+ change_target_tiling = true;
+ }
+
+ // Always match the ideal device scale factor.
+ if (raster_device_scale_ != ideal_device_scale_)
+ change_target_tiling = true;
+
+ if (!change_target_tiling)
+ return;
+
+ raster_page_scale_ = ideal_page_scale_;
+ raster_device_scale_ = ideal_device_scale_;
+ raster_source_scale_ = ideal_source_scale_;
+
+ // Don't allow animating CSS scales to drop below 1.
+ if (is_animating)
+ raster_source_scale_ = std::max(raster_source_scale_, 1.f);
+
+ float raster_contents_scale =
+ raster_page_scale_ * raster_device_scale_ * raster_source_scale_;
+ float low_res_raster_contents_scale = std::max(
+ raster_contents_scale * low_res_factor,
+ layerTreeImpl()->settings().minimumContentsScale);
+
PictureLayerTiling* high_res = NULL;
PictureLayerTiling* low_res = NULL;
- PictureLayerTiling* old_high_res = NULL;
- PictureLayerTiling* old_low_res = NULL;
- // Find existing tilings closest to ideal high / low res.
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))
+ if (tiling->contents_scale() == raster_contents_scale)
high_res = tiling;
- if (!low_res || IsCloserToThan(tiling, low_res, low_res_contents_scale))
+ if (tiling->contents_scale() == low_res_raster_contents_scale)
low_res = tiling;
- if (tiling->resolution() == HIGH_RESOLUTION)
- old_high_res = tiling;
- else if (tiling->resolution() == LOW_RESOLUTION)
- old_low_res = tiling;
-
// Reset all tilings to non-ideal until the end of this function.
tiling->set_resolution(NON_IDEAL_RESOLUTION);
}
- if (is_animating && old_high_res)
- high_res = old_high_res;
- if (is_animating && old_low_res)
- low_res = old_low_res;
-
- 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 {
- bool high_res_mismatch = !is_animating && high_res &&
- high_res->contents_scale() != ideal_contents_scale;
- bool low_res_mismatch = !is_animating && low_res &&
- low_res->contents_scale() != low_res_contents_scale;
-
- // Always make sure we have some tiling.
- if (!high_res || high_res_mismatch)
- high_res = AddTiling(ideal_contents_scale);
-
- // If we're not pinching then add a low res tiling at the exact scale.
- if (!layerTreeImpl()->PinchGestureActive()) {
- if (!low_res || low_res_mismatch)
- low_res = AddTiling(low_res_contents_scale);
- }
- }
+ if (!high_res)
+ high_res = AddTiling(raster_contents_scale);
+ if (!low_res && low_res != high_res)
+ low_res = AddTiling(low_res_raster_contents_scale);
if (high_res)
high_res->set_resolution(HIGH_RESOLUTION);
@@ -552,22 +600,85 @@ void PictureLayerImpl::ManageTilings(float ideal_contents_scale) {
low_res->set_resolution(LOW_RESOLUTION);
}
-void PictureLayerImpl::CleanUpUnusedTilings(
+void PictureLayerImpl::CleanUpTilingsOnActiveLayer(
std::vector<PictureLayerTiling*> used_tilings) {
- std::vector<PictureLayerTiling*> to_remove;
+ DCHECK(layerTreeImpl()->IsActiveTree());
+ float raster_contents_scale =
+ raster_page_scale_ * raster_device_scale_ * raster_source_scale_;
+
+ float min_acceptable_high_res_scale = std::min(
+ raster_contents_scale, ideal_contents_scale_);
+ float max_acceptable_high_res_scale = std::max(
+ raster_contents_scale, ideal_contents_scale_);
+
+ PictureLayerImpl* twin = PendingTwin();
+ if (twin) {
+ float twin_raster_contents_scale =
+ twin->raster_page_scale_ *
+ twin->raster_device_scale_ *
+ twin->raster_source_scale_;
+
+ min_acceptable_high_res_scale = std::min(
+ min_acceptable_high_res_scale,
+ std::min(twin_raster_contents_scale, twin->ideal_contents_scale_));
+ max_acceptable_high_res_scale = std::max(
+ max_acceptable_high_res_scale,
+ std::max(twin_raster_contents_scale, twin->ideal_contents_scale_));
+ }
+
+ float low_res_factor = layerTreeImpl()->settings().lowResContentsScaleFactor;
+
+ float min_acceptable_low_res_scale =
+ low_res_factor * min_acceptable_high_res_scale;
+ float max_acceptable_low_res_scale =
+ low_res_factor * max_acceptable_high_res_scale;
+
+ 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)
+
+ if (tiling->contents_scale() >= min_acceptable_high_res_scale &&
+ tiling->contents_scale() <= max_acceptable_high_res_scale)
+ continue;
+
+ if (tiling->contents_scale() >= min_acceptable_low_res_scale &&
+ tiling->contents_scale() <= max_acceptable_low_res_scale)
continue;
- if (std::find(used_tilings.begin(), used_tilings.end(), tiling) ==
+
+ // Don't remove tilings that are being used and expected to stay around.
+ if (std::find(used_tilings.begin(), used_tilings.end(), tiling) !=
used_tilings.end())
- to_remove.push_back(tiling);
+ continue;
+
+ to_remove.push_back(tiling);
}
- for (size_t i = 0; i < to_remove.size(); ++i)
+ for (size_t i = 0; i < to_remove.size(); ++i) {
+ if (twin)
+ twin->RemoveTiling(to_remove[i]->contents_scale());
tilings_->Remove(to_remove[i]);
+ }
+}
+
+PictureLayerImpl* PictureLayerImpl::PendingTwin() const {
+ DCHECK(layerTreeImpl()->IsActiveTree());
+
+ PictureLayerImpl* twin = static_cast<PictureLayerImpl*>(
+ layerTreeImpl()->FindPendingTreeLayerById(id()));
+ if (twin)
+ DCHECK_EQ(id(), twin->id());
+ return twin;
+}
+
+PictureLayerImpl* PictureLayerImpl::ActiveTwin() const {
+ DCHECK(layerTreeImpl()->IsPendingTree());
+
+ PictureLayerImpl* twin = static_cast<PictureLayerImpl*>(
+ layerTreeImpl()->FindActiveTreeLayerById(id()));
+ if (twin)
+ DCHECK_EQ(id(), twin->id());
+ return twin;
}
void PictureLayerImpl::getDebugBorderProperties(
diff --git a/cc/picture_layer_impl.h b/cc/picture_layer_impl.h
index 243548a..bedf457 100644
--- a/cc/picture_layer_impl.h
+++ b/cc/picture_layer_impl.h
@@ -67,10 +67,14 @@ public:
protected:
PictureLayerImpl(LayerTreeImpl* treeImpl, int id);
PictureLayerTiling* AddTiling(float contents_scale);
+ void RemoveTiling(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);
+ void ManageTilings();
+ void CleanUpTilingsOnActiveLayer(
+ std::vector<PictureLayerTiling*> used_tilings);
+ PictureLayerImpl* PendingTwin() const;
+ PictureLayerImpl* ActiveTwin() const;
virtual void getDebugBorderProperties(
SkColor* color, float* width) const OVERRIDE;
@@ -86,6 +90,15 @@ protected:
float ideal_contents_scale_;
bool is_mask_;
+ float ideal_page_scale_;
+ float ideal_device_scale_;
+ float ideal_source_scale_;
+
+ float raster_page_scale_;
+ float raster_device_scale_;
+ float raster_source_scale_;
+ bool raster_source_scale_was_animating_;
+
friend class PictureLayer;
DISALLOW_COPY_AND_ASSIGN(PictureLayerImpl);
};
diff --git a/cc/picture_layer_impl_unittest.cc b/cc/picture_layer_impl_unittest.cc
index 3e0cba1..9ead881 100644
--- a/cc/picture_layer_impl_unittest.cc
+++ b/cc/picture_layer_impl_unittest.cc
@@ -29,6 +29,7 @@ class TestablePictureLayerImpl : public PictureLayerImpl {
Region& invalidation() { return invalidation_; }
using PictureLayerImpl::AddTiling;
+ using PictureLayerImpl::CleanUpTilingsOnActiveLayer;
private:
TestablePictureLayerImpl(
@@ -172,6 +173,15 @@ class PictureLayerImplTest : public testing::Test {
}
}
+ void SetContentsScaleOnBothLayers(float scale) {
+ float result_scale_x, result_scale_y;
+ gfx::Size result_bounds;
+ pending_layer_->calculateContentsScale(
+ scale, &result_scale_x, &result_scale_y, &result_bounds);
+ active_layer_->calculateContentsScale(
+ scale, &result_scale_x, &result_scale_y, &result_bounds);
+ }
+
protected:
FakeImplProxy proxy_;
FakeLayerTreeHostImpl host_impl_;
@@ -360,5 +370,229 @@ TEST_F(PictureLayerImplTest, addTilesFromNewRecording) {
}
}
+TEST_F(PictureLayerImplTest, ManageTilingsWithNoRecording) {
+ gfx::Size tile_size(400, 400);
+ gfx::Size layer_bounds(1300, 1900);
+
+ scoped_refptr<TestablePicturePileImpl> pending_pile =
+ TestablePicturePileImpl::CreateEmptyPile(tile_size, layer_bounds);
+ scoped_refptr<TestablePicturePileImpl> active_pile =
+ TestablePicturePileImpl::CreateEmptyPile(tile_size, layer_bounds);
+
+ float result_scale_x, result_scale_y;
+ gfx::Size result_bounds;
+
+ SetupTrees(pending_pile, active_pile);
+
+ // These are included in the scale given to the layer.
+ host_impl_.setDeviceScaleFactor(1.f);
+ host_impl_.pendingTree()->SetPageScaleFactorAndLimits(1.f, 1.f, 1.f);
+
+ pending_layer_->calculateContentsScale(
+ 1.f, &result_scale_x, &result_scale_y, &result_bounds);
+
+ EXPECT_EQ(0u, pending_layer_->tilings().num_tilings());
+}
+
+TEST_F(PictureLayerImplTest, ManageTilingsCreatesTilings) {
+ gfx::Size tile_size(400, 400);
+ gfx::Size layer_bounds(1300, 1900);
+
+ scoped_refptr<TestablePicturePileImpl> pending_pile =
+ TestablePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ scoped_refptr<TestablePicturePileImpl> active_pile =
+ TestablePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+
+ float result_scale_x, result_scale_y;
+ gfx::Size result_bounds;
+
+ SetupTrees(pending_pile, active_pile);
+ EXPECT_EQ(0u, pending_layer_->tilings().num_tilings());
+
+ float low_res_factor = host_impl_.settings().lowResContentsScaleFactor;
+ EXPECT_LT(low_res_factor, 1.f);
+
+ // These are included in the scale given to the layer.
+ host_impl_.setDeviceScaleFactor(1.7f);
+ host_impl_.pendingTree()->SetPageScaleFactorAndLimits(3.2f, 3.2f, 3.2f);
+
+ pending_layer_->calculateContentsScale(
+ 1.3f, &result_scale_x, &result_scale_y, &result_bounds);
+ ASSERT_EQ(2u, pending_layer_->tilings().num_tilings());
+ EXPECT_FLOAT_EQ(
+ 1.3f,
+ pending_layer_->tilings().tiling_at(0)->contents_scale());
+ EXPECT_FLOAT_EQ(
+ 1.3f * low_res_factor,
+ pending_layer_->tilings().tiling_at(1)->contents_scale());
+
+ // If we change the layer's CSS scale factor, then we should not get new
+ // tilings.
+ pending_layer_->calculateContentsScale(
+ 1.8f, &result_scale_x, &result_scale_y, &result_bounds);
+ ASSERT_EQ(2u, pending_layer_->tilings().num_tilings());
+ EXPECT_FLOAT_EQ(
+ 1.3f,
+ pending_layer_->tilings().tiling_at(0)->contents_scale());
+ EXPECT_FLOAT_EQ(
+ 1.3f * low_res_factor,
+ pending_layer_->tilings().tiling_at(1)->contents_scale());
+
+ // If we change the page scale factor, then we should get new tilings.
+ host_impl_.pendingTree()->SetPageScaleFactorAndLimits(2.2f, 2.2f, 2.2f);
+
+ pending_layer_->calculateContentsScale(
+ 1.8f, &result_scale_x, &result_scale_y, &result_bounds);
+ ASSERT_EQ(4u, pending_layer_->tilings().num_tilings());
+ EXPECT_FLOAT_EQ(
+ 1.8f,
+ pending_layer_->tilings().tiling_at(0)->contents_scale());
+ EXPECT_FLOAT_EQ(
+ 1.8f * low_res_factor,
+ pending_layer_->tilings().tiling_at(2)->contents_scale());
+
+ // If we change the device scale factor, then we should get new tilings.
+ host_impl_.setDeviceScaleFactor(1.4f);
+
+ pending_layer_->calculateContentsScale(
+ 1.9f, &result_scale_x, &result_scale_y, &result_bounds);
+ ASSERT_EQ(6u, pending_layer_->tilings().num_tilings());
+ EXPECT_FLOAT_EQ(
+ 1.9f,
+ pending_layer_->tilings().tiling_at(0)->contents_scale());
+ EXPECT_FLOAT_EQ(
+ 1.9f * low_res_factor,
+ pending_layer_->tilings().tiling_at(3)->contents_scale());
+
+ // If we change the device scale factor, but end up at the same total scale
+ // factor somehow, then we don't get new tilings.
+ host_impl_.setDeviceScaleFactor(2.2f);
+ host_impl_.pendingTree()->SetPageScaleFactorAndLimits(1.4f, 1.4f, 1.4f);
+
+ pending_layer_->calculateContentsScale(
+ 1.9f, &result_scale_x, &result_scale_y, &result_bounds);
+ ASSERT_EQ(6u, pending_layer_->tilings().num_tilings());
+ EXPECT_FLOAT_EQ(
+ 1.9f,
+ pending_layer_->tilings().tiling_at(0)->contents_scale());
+ EXPECT_FLOAT_EQ(
+ 1.9f * low_res_factor,
+ pending_layer_->tilings().tiling_at(3)->contents_scale());
+}
+
+TEST_F(PictureLayerImplTest, CleanUpTilings) {
+ gfx::Size tile_size(400, 400);
+ gfx::Size layer_bounds(1300, 1900);
+
+ scoped_refptr<TestablePicturePileImpl> pending_pile =
+ TestablePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ scoped_refptr<TestablePicturePileImpl> active_pile =
+ TestablePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+
+ float result_scale_x, result_scale_y;
+ gfx::Size result_bounds;
+ std::vector<PictureLayerTiling*> used_tilings;
+
+ SetupTrees(pending_pile, active_pile);
+ EXPECT_EQ(0u, pending_layer_->tilings().num_tilings());
+
+ float low_res_factor = host_impl_.settings().lowResContentsScaleFactor;
+ EXPECT_LT(low_res_factor, 1.f);
+
+ // These are included in the scale given to the layer.
+ host_impl_.setDeviceScaleFactor(1.7f);
+ host_impl_.pendingTree()->SetPageScaleFactorAndLimits(3.2f, 3.2f, 3.2f);
+ host_impl_.activeTree()->SetPageScaleFactorAndLimits(3.2f, 3.2f, 3.2f);
+
+ SetContentsScaleOnBothLayers(1.f);
+ ASSERT_EQ(2u, active_layer_->tilings().num_tilings());
+
+ // We only have ideal tilings, so they aren't removed.
+ used_tilings.clear();
+ active_layer_->CleanUpTilingsOnActiveLayer(used_tilings);
+ ASSERT_EQ(2u, active_layer_->tilings().num_tilings());
+
+ // Changing the ideal but not creating new tilings.
+ SetContentsScaleOnBothLayers(1.5f);
+ ASSERT_EQ(2u, active_layer_->tilings().num_tilings());
+
+ // The tilings are still our target scale, so they aren't removed.
+ used_tilings.clear();
+ active_layer_->CleanUpTilingsOnActiveLayer(used_tilings);
+ ASSERT_EQ(2u, active_layer_->tilings().num_tilings());
+
+ // Create a 1.2 scale tiling. Now we have 1.0 and 1.2 tilings. Ideal = 1.2.
+ host_impl_.pendingTree()->SetPageScaleFactorAndLimits(1.2f, 1.2f, 1.2f);
+ host_impl_.activeTree()->SetPageScaleFactorAndLimits(1.2f, 1.2f, 1.2f);
+ SetContentsScaleOnBothLayers(1.2f);
+ ASSERT_EQ(4u, active_layer_->tilings().num_tilings());
+ EXPECT_FLOAT_EQ(
+ 1.f,
+ active_layer_->tilings().tiling_at(1)->contents_scale());
+ EXPECT_FLOAT_EQ(
+ 1.f * low_res_factor,
+ active_layer_->tilings().tiling_at(3)->contents_scale());
+
+ // Mark the non-ideal tilings as used. They won't be removed.
+ used_tilings.clear();
+ used_tilings.push_back(active_layer_->tilings().tiling_at(1));
+ used_tilings.push_back(active_layer_->tilings().tiling_at(3));
+ active_layer_->CleanUpTilingsOnActiveLayer(used_tilings);
+ ASSERT_EQ(4u, active_layer_->tilings().num_tilings());
+
+ // Now move the ideal scale to 0.5. Our target stays 1.2.
+ SetContentsScaleOnBothLayers(0.5f);
+
+ // All the tilings are between are target and the ideal, so they are not
+ // removed.
+ used_tilings.clear();
+ active_layer_->CleanUpTilingsOnActiveLayer(used_tilings);
+ ASSERT_EQ(4u, active_layer_->tilings().num_tilings());
+
+ // Now move the ideal scale to 1.0. Our target stays 1.2.
+ SetContentsScaleOnBothLayers(1.f);
+
+ // All the tilings are between are target and the ideal, so they are not
+ // removed.
+ used_tilings.clear();
+ active_layer_->CleanUpTilingsOnActiveLayer(used_tilings);
+ ASSERT_EQ(4u, active_layer_->tilings().num_tilings());
+
+ // Now move the ideal scale to 1.1 on the active layer. Our target stays 1.2.
+ active_layer_->calculateContentsScale(
+ 1.1f, &result_scale_x, &result_scale_y, &result_bounds);
+
+ // Because the pending layer's ideal scale is still 1.0, our tilings fall
+ // in the range [1.0,1.2] and are kept.
+ used_tilings.clear();
+ active_layer_->CleanUpTilingsOnActiveLayer(used_tilings);
+ ASSERT_EQ(4u, active_layer_->tilings().num_tilings());
+
+ // Move the ideal scale on the pending layer to 1.1 as well. Our target stays
+ // 1.2 still.
+ pending_layer_->calculateContentsScale(
+ 1.1f, &result_scale_x, &result_scale_y, &result_bounds);
+
+ // Our 1.0 tiling now falls outside the range between our ideal scale and our
+ // target raster scale. But it is in our used tilings set, so nothing is
+ // deleted.
+ used_tilings.clear();
+ used_tilings.push_back(active_layer_->tilings().tiling_at(1));
+ used_tilings.push_back(active_layer_->tilings().tiling_at(3));
+ active_layer_->CleanUpTilingsOnActiveLayer(used_tilings);
+ ASSERT_EQ(4u, active_layer_->tilings().num_tilings());
+
+ // If we remove it from our used tilings set, it is outside the range to keep
+ // so it is deleted. Try one tiling at a time.
+ used_tilings.clear();
+ used_tilings.push_back(active_layer_->tilings().tiling_at(1));
+ active_layer_->CleanUpTilingsOnActiveLayer(used_tilings);
+ ASSERT_EQ(3u, active_layer_->tilings().num_tilings());
+ used_tilings.clear();
+ active_layer_->CleanUpTilingsOnActiveLayer(used_tilings);
+ ASSERT_EQ(2u, active_layer_->tilings().num_tilings());
+
+}
+
} // namespace
} // namespace cc