diff options
author | epenner@chromium.org <epenner@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-20 03:58:08 +0000 |
---|---|---|
committer | epenner@chromium.org <epenner@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-20 03:58:08 +0000 |
commit | 834474724d39dab69252b8291ef5cb584147bd71 (patch) | |
tree | cec30bc3734f81a69eb65f348261d166b2185ac1 /cc/layers | |
parent | a503807483c3242bb4e758a332177bbd1c2a36db (diff) | |
download | chromium_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.cc | 13 | ||||
-rw-r--r-- | cc/layers/picture_image_layer_impl.h | 6 | ||||
-rw-r--r-- | cc/layers/picture_layer_impl.cc | 76 | ||||
-rw-r--r-- | cc/layers/picture_layer_impl.h | 7 | ||||
-rw-r--r-- | cc/layers/picture_layer_impl_unittest.cc | 58 |
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); |