Chromium Code Reviews| Index: cc/picture_layer_impl.cc |
| diff --git a/cc/picture_layer_impl.cc b/cc/picture_layer_impl.cc |
| index e4c113a5aac5e9ce34d91998d77664cbe8e5b43d..6148db843418ac48f8ca09de8321bdc7c8c5e610 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 |
| @@ -239,7 +259,10 @@ void PictureLayerImpl::SetIsMask(bool is_mask) { |
| 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. |
| @@ -253,25 +276,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 { |
| @@ -285,18 +309,109 @@ 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 that don't exactly match the contents scale from the |
|
danakj
2013/01/09 00:22:49
nit: Remove any tilings from the pending tree that
enne (OOO)
2013/01/09 00:38:38
Done.
|
| + // pending tree. 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; |
| + else if (tiling->contents_scale() == low_res_contents_scale) |
|
danakj
2013/01/09 00:22:49
nit: don't need the else
enne (OOO)
2013/01/09 00:38:38
No, but I'd have to put it on multiple lines anywa
danakj
2013/01/09 00:40:20
I mean you don't need the "else" part. Just the if
|
| + 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]); |
|
danakj
2013/01/09 00:22:49
n^2 removal :/ i take it the sizes here aren't lar
enne (OOO)
2013/01/09 00:38:38
Yes, n <= 4 99% of the time, and maybe n <= 6 if y
|
| } |
| + |
| + // Find existing tilings closest to ideal high / low res |
|
danakj
2013/01/09 00:22:49
nit: period
enne (OOO)
2013/01/09 00:38:38
Done.
|
| + 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); |
|
danakj
2013/01/09 00:22:49
why do you add a low res during pinch here? but no
enne (OOO)
2013/01/09 00:38:38
If the high res is bad, then you at least still ha
|
| + } |
| + } |
| + |
| + 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) { |
|
danakj
2013/01/09 00:22:49
nit: used_tilings (match the name in the header)
enne (OOO)
2013/01/09 00:38:38
Variable name short for 80 col. /o\ Done.
|
| + 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.begin(), used.end(), tiling) == used.end()) |
| + to_remove.push_back(tiling); |
| + } |
| + |
| + for (size_t i = 0; i < to_remove.size(); ++i) |
| + tilings_.Remove(to_remove[i]); |
|
danakj
2013/01/09 00:22:49
n^2 again, it's okay?
enne (OOO)
2013/01/09 00:38:38
Yes.
|
| } |
| } // namespace cc |