summaryrefslogtreecommitdiffstats
path: root/cc/layers
diff options
context:
space:
mode:
authorepenner@chromium.org <epenner@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-11-20 03:58:08 +0000
committerepenner@chromium.org <epenner@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-11-20 03:58:08 +0000
commit834474724d39dab69252b8291ef5cb584147bd71 (patch)
treecec30bc3734f81a69eb65f348261d166b2185ac1 /cc/layers
parenta503807483c3242bb4e758a332177bbd1c2a36db (diff)
downloadchromium_src-834474724d39dab69252b8291ef5cb584147bd71.zip
chromium_src-834474724d39dab69252b8291ef5cb584147bd71.tar.gz
chromium_src-834474724d39dab69252b8291ef5cb584147bd71.tar.bz2
We used to create tilings only when exceeding a certain scale
difference from the ideal scale. This meant that in the worst case our only available high-res tiling was 2X the required resolution. This patch adjusts the creation of new tilings, to ensure we always have a tiling option that is less-than-or-equal-to the current ideal scale. BUG=307206 Review URL: https://codereview.chromium.org/27251002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@236129 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc/layers')
-rw-r--r--cc/layers/picture_image_layer_impl.cc13
-rw-r--r--cc/layers/picture_image_layer_impl.h6
-rw-r--r--cc/layers/picture_layer_impl.cc76
-rw-r--r--cc/layers/picture_layer_impl.h7
-rw-r--r--cc/layers/picture_layer_impl_unittest.cc58
5 files changed, 124 insertions, 36 deletions
diff --git a/cc/layers/picture_image_layer_impl.cc b/cc/layers/picture_image_layer_impl.cc
index 199aec3..b9a57f2 100644
--- a/cc/layers/picture_image_layer_impl.cc
+++ b/cc/layers/picture_image_layer_impl.cc
@@ -58,15 +58,16 @@ bool PictureImageLayerImpl::ShouldAdjustRasterScale(
return false;
}
-void PictureImageLayerImpl::CalculateRasterContentsScale(
- bool animating_transform_to_screen,
- float* raster_contents_scale,
- float* low_res_raster_contents_scale) const {
+void PictureImageLayerImpl::RecalculateRasterScales(
+ bool animating_transform_to_screen) {
+ // Defaults from PictureLayerImpl.
+ PictureLayerImpl::RecalculateRasterScales(animating_transform_to_screen);
+
// Don't scale images during rastering to ensure image quality, save memory
// and avoid frequent re-rastering on change of scale.
- *raster_contents_scale = std::max(1.f, MinimumContentsScale());
+ raster_contents_scale_ = std::max(1.f, MinimumContentsScale());
// We don't need low res tiles.
- *low_res_raster_contents_scale = *raster_contents_scale;
+ low_res_raster_contents_scale_ = raster_contents_scale_;
}
} // namespace cc
diff --git a/cc/layers/picture_image_layer_impl.h b/cc/layers/picture_image_layer_impl.h
index c475e53..0b3b246 100644
--- a/cc/layers/picture_image_layer_impl.h
+++ b/cc/layers/picture_image_layer_impl.h
@@ -34,10 +34,8 @@ class CC_EXPORT PictureImageLayerImpl : public PictureLayerImpl {
virtual bool ShouldAdjustRasterScale(
bool animating_transform_to_screen) const OVERRIDE;
- virtual void CalculateRasterContentsScale(
- bool animating_transform_to_screen,
- float* raster_contents_scale,
- float* low_res_raster_contents_scale) const OVERRIDE;
+ virtual void RecalculateRasterScales(
+ bool animating_transform_to_screen) OVERRIDE;
virtual void GetDebugBorderProperties(
SkColor* color, float* width) const OVERRIDE;
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc
index 5e752c6..86f45b6 100644
--- a/cc/layers/picture_layer_impl.cc
+++ b/cc/layers/picture_layer_impl.cc
@@ -5,6 +5,7 @@
#include "cc/layers/picture_layer_impl.h"
#include <algorithm>
+#include <limits>
#include "base/time/time.h"
#include "cc/base/math_util.h"
@@ -27,6 +28,10 @@
namespace {
const float kMaxScaleRatioDuringPinch = 2.0f;
+
+// When creating a new tiling during pinch, snap to an existing
+// tiling's scale if the desired scale is within this ratio.
+const float kSnapToExistingTilingRatio = 0.2f;
}
namespace cc {
@@ -816,13 +821,7 @@ void PictureLayerImpl::ManageTilings(bool animating_transform_to_screen) {
if (!layer_tree_impl()->device_viewport_valid_for_tile_management())
return;
- raster_page_scale_ = ideal_page_scale_;
- raster_device_scale_ = ideal_device_scale_;
- raster_source_scale_ = ideal_source_scale_;
-
- CalculateRasterContentsScale(animating_transform_to_screen,
- &raster_contents_scale_,
- &low_res_raster_contents_scale_);
+ RecalculateRasterScales(animating_transform_to_screen);
PictureLayerTiling* high_res = NULL;
PictureLayerTiling* low_res = NULL;
@@ -876,10 +875,12 @@ bool PictureLayerImpl::ShouldAdjustRasterScale(
bool is_pinching = layer_tree_impl()->PinchGestureActive();
if (is_pinching && raster_page_scale_) {
- // 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)
+ // We change our raster scale when it is:
+ // - Higher than ideal (need a lower-res tiling available)
+ // - Too far from ideal (need a higher-res tiling available)
+ float ratio = ideal_page_scale_ / raster_page_scale_;
+ if (raster_page_scale_ > ideal_page_scale_ ||
+ ratio > kMaxScaleRatioDuringPinch)
return true;
}
@@ -896,35 +897,66 @@ bool PictureLayerImpl::ShouldAdjustRasterScale(
return false;
}
-void PictureLayerImpl::CalculateRasterContentsScale(
- bool animating_transform_to_screen,
- float* raster_contents_scale,
- float* low_res_raster_contents_scale) const {
- *raster_contents_scale = ideal_contents_scale_;
+float PictureLayerImpl::SnappedContentsScale(float scale) {
+ // If a tiling exists within the max snapping ratio, snap to its scale.
+ float snapped_contents_scale = scale;
+ float snapped_ratio = kSnapToExistingTilingRatio;
+ for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
+ float tiling_contents_scale = tilings_->tiling_at(i)->contents_scale();
+ float ratio = PositiveRatio(tiling_contents_scale, scale);
+ if (ratio < snapped_ratio) {
+ snapped_contents_scale = tiling_contents_scale;
+ snapped_ratio = ratio;
+ }
+ }
+ return snapped_contents_scale;
+}
+
+void PictureLayerImpl::RecalculateRasterScales(
+ bool animating_transform_to_screen) {
+ raster_device_scale_ = ideal_device_scale_;
+ raster_source_scale_ = ideal_source_scale_;
+
+ bool is_pinching = layer_tree_impl()->PinchGestureActive();
+ if (!is_pinching) {
+ // When not pinching, we use ideal scale:
+ raster_page_scale_ = ideal_page_scale_;
+ raster_contents_scale_ = ideal_contents_scale_;
+ } else {
+ // See ShouldAdjustRasterScale:
+ // - When zooming out, preemptively create new tiling at lower resolution.
+ // - When zooming in, approximate ideal using multiple of kMaxScaleRatio.
+ bool zooming_out = raster_page_scale_ > ideal_page_scale_;
+ float desired_contents_scale =
+ zooming_out ? raster_contents_scale_ / kMaxScaleRatioDuringPinch
+ : raster_contents_scale_ * kMaxScaleRatioDuringPinch;
+ raster_contents_scale_ = SnappedContentsScale(desired_contents_scale);
+ raster_page_scale_ = raster_contents_scale_ / raster_device_scale_;
+ }
// Don't allow animating CSS scales to drop below 1. This is needed because
// changes in raster source scale aren't handled. See the comment in
// ShouldAdjustRasterScale.
if (animating_transform_to_screen) {
- *raster_contents_scale = std::max(
- *raster_contents_scale, 1.f * ideal_page_scale_ * ideal_device_scale_);
+ raster_contents_scale_ = std::max(
+ raster_contents_scale_, 1.f * ideal_page_scale_ * ideal_device_scale_);
}
// If this layer would only create one tile at this content scale,
// don't create a low res tiling.
gfx::Size content_bounds =
- gfx::ToCeiledSize(gfx::ScaleSize(bounds(), *raster_contents_scale));
+ gfx::ToCeiledSize(gfx::ScaleSize(bounds(), raster_contents_scale_));
gfx::Size tile_size = CalculateTileSize(content_bounds);
if (tile_size.width() >= content_bounds.width() &&
tile_size.height() >= content_bounds.height()) {
- *low_res_raster_contents_scale = *raster_contents_scale;
+ low_res_raster_contents_scale_ = raster_contents_scale_;
return;
}
float low_res_factor =
layer_tree_impl()->settings().low_res_contents_scale_factor;
- *low_res_raster_contents_scale = std::max(
- *raster_contents_scale * low_res_factor,
+ low_res_raster_contents_scale_ = std::max(
+ raster_contents_scale_ * low_res_factor,
MinimumContentsScale());
}
diff --git a/cc/layers/picture_layer_impl.h b/cc/layers/picture_layer_impl.h
index de322ea..f431de8 100644
--- a/cc/layers/picture_layer_impl.h
+++ b/cc/layers/picture_layer_impl.h
@@ -81,13 +81,12 @@ class CC_EXPORT PictureLayerImpl
void ManageTilings(bool animating_transform_to_screen);
virtual bool ShouldAdjustRasterScale(
bool animating_transform_to_screen) const;
- virtual void CalculateRasterContentsScale(
- bool animating_transform_to_screen,
- float* raster_contents_scale,
- float* low_res_raster_contents_scale) const;
+ virtual void RecalculateRasterScales(
+ bool animating_transform_to_screen);
void CleanUpTilingsOnActiveLayer(
std::vector<PictureLayerTiling*> used_tilings);
float MinimumContentsScale() const;
+ float SnappedContentsScale(float new_contents_scale);
void UpdateLCDTextStatus(bool new_status);
void ResetRasterScale();
void MarkVisibleResourcesAsRequired() const;
diff --git a/cc/layers/picture_layer_impl_unittest.cc b/cc/layers/picture_layer_impl_unittest.cc
index 716d50d..48458d7 100644
--- a/cc/layers/picture_layer_impl_unittest.cc
+++ b/cc/layers/picture_layer_impl_unittest.cc
@@ -591,6 +591,64 @@ TEST_F(PictureLayerImplTest, ManageTilingsCreatesTilings) {
pending_layer_->tilings()->tiling_at(3)->contents_scale());
}
+TEST_F(PictureLayerImplTest, PinchGestureTilings) {
+ gfx::Size tile_size(400, 400);
+ gfx::Size layer_bounds(1300, 1900);
+
+ scoped_refptr<FakePicturePileImpl> pending_pile =
+ FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ scoped_refptr<FakePicturePileImpl> active_pile =
+ FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+
+ // Set up the high and low res tilings before pinch zoom.
+ SetupTrees(pending_pile, active_pile);
+ EXPECT_EQ(0u, active_layer_->tilings()->num_tilings());
+ SetContentsScaleOnBothLayers(1.0f, 1.0f, 1.0f, false);
+ float low_res_factor = host_impl_.settings().low_res_contents_scale_factor;
+ EXPECT_EQ(2u, active_layer_->tilings()->num_tilings());
+ EXPECT_FLOAT_EQ(
+ 1.0f,
+ active_layer_->tilings()->tiling_at(0)->contents_scale());
+ EXPECT_FLOAT_EQ(
+ 1.0f * low_res_factor,
+ active_layer_->tilings()->tiling_at(1)->contents_scale());
+
+ // Start a pinch gesture.
+ host_impl_.PinchGestureBegin();
+
+ // Zoom out by a small amount. We should create a tiling at half
+ // the scale (1/kMaxScaleRatioDuringPinch).
+ SetContentsScaleOnBothLayers(0.90f, 1.0f, 0.9f, false);
+ EXPECT_EQ(3u, active_layer_->tilings()->num_tilings());
+ EXPECT_FLOAT_EQ(
+ 1.0f,
+ active_layer_->tilings()->tiling_at(0)->contents_scale());
+ EXPECT_FLOAT_EQ(
+ 0.5f,
+ active_layer_->tilings()->tiling_at(1)->contents_scale());
+ EXPECT_FLOAT_EQ(
+ 1.0f * low_res_factor,
+ active_layer_->tilings()->tiling_at(2)->contents_scale());
+
+ // Zoom out further, close to our low-res scale factor. We should
+ // use that tiling as high-res, and not create a new tiling.
+ SetContentsScaleOnBothLayers(low_res_factor, 1.0f, low_res_factor, false);
+ EXPECT_EQ(3u, active_layer_->tilings()->num_tilings());
+
+ // Zoom in a lot now. Since we increase by increments of
+ // kMaxScaleRatioDuringPinch, this will first use 0.5, then 1.0
+ // and then finally create a new tiling at 2.0.
+ SetContentsScaleOnBothLayers(2.1f, 1.0f, 2.1f, false);
+ EXPECT_EQ(3u, active_layer_->tilings()->num_tilings());
+ SetContentsScaleOnBothLayers(2.1f, 1.0f, 2.1f, false);
+ EXPECT_EQ(3u, active_layer_->tilings()->num_tilings());
+ SetContentsScaleOnBothLayers(2.1f, 1.0f, 2.1f, false);
+ EXPECT_EQ(4u, active_layer_->tilings()->num_tilings());
+ EXPECT_FLOAT_EQ(
+ 2.0f,
+ active_layer_->tilings()->tiling_at(0)->contents_scale());
+}
+
TEST_F(PictureLayerImplTest, CleanUpTilings) {
gfx::Size tile_size(400, 400);
gfx::Size layer_bounds(1300, 1900);