diff options
Diffstat (limited to 'cc')
37 files changed, 618 insertions, 187 deletions
diff --git a/cc/BUILD.gn b/cc/BUILD.gn index a5a7126..fb07c2e 100644 --- a/cc/BUILD.gn +++ b/cc/BUILD.gn @@ -322,6 +322,8 @@ component("cc") { "proto/image_serialization_processor.h", "proto/skia_conversions.cc", "proto/skia_conversions.h", + "proto/synced_property_conversions.cc", + "proto/synced_property_conversions.h", "quads/content_draw_quad_base.cc", "quads/content_draw_quad_base.h", "quads/debug_border_draw_quad.cc", @@ -838,6 +840,7 @@ test("cc_unittests") { "proto/gfx_conversions_unittest.cc", "proto/gpu_conversions_unittest.cc", "proto/skia_conversions_unittest.cc", + "proto/synced_property_conversions_unittest.cc", "quads/draw_polygon_unittest.cc", "quads/draw_quad_unittest.cc", "quads/render_pass_unittest.cc", diff --git a/cc/base/synced_property.h b/cc/base/synced_property.h index 6b02e7a6..7d1e563 100644 --- a/cc/base/synced_property.h +++ b/cc/base/synced_property.h @@ -113,6 +113,7 @@ class SyncedProperty : public base::RefCounted<SyncedProperty<T>> { } void set_clobber_active_value() { clobber_active_value_ = true; } + bool clobber_active_value() const { return clobber_active_value_; } private: // Value last committed to the pending tree. @@ -384,6 +384,8 @@ 'proto/image_serialization_processor.h', 'proto/skia_conversions.cc', 'proto/skia_conversions.h', + 'proto/synced_property_conversions.cc', + 'proto/synced_property_conversions.h', 'quads/content_draw_quad_base.cc', 'quads/content_draw_quad_base.h', 'quads/debug_border_draw_quad.cc', @@ -637,6 +639,7 @@ 'proto/skregion.proto', 'proto/skrrect.proto', 'proto/skxfermode.proto', + 'proto/synced_property.proto', 'proto/transform.proto', 'proto/vector2d.proto', 'proto/vector2df.proto', diff --git a/cc/cc_tests.gyp b/cc/cc_tests.gyp index 30e948a..dd84cd7 100644 --- a/cc/cc_tests.gyp +++ b/cc/cc_tests.gyp @@ -92,6 +92,7 @@ 'proto/gfx_conversions_unittest.cc', 'proto/gpu_conversions_unittest.cc', 'proto/skia_conversions_unittest.cc', + 'proto/synced_property_conversions_unittest.cc', 'quads/draw_polygon_unittest.cc', 'quads/draw_quad_unittest.cc', 'quads/render_pass_unittest.cc', diff --git a/cc/input/scroll_state.cc b/cc/input/scroll_state.cc index aa0baf1..f0c0d7e 100644 --- a/cc/input/scroll_state.cc +++ b/cc/input/scroll_state.cc @@ -10,7 +10,8 @@ namespace cc { -ScrollState::ScrollState(ScrollStateData data) : data_(data) {} +ScrollState::ScrollState(ScrollStateData data) + : data_(data), layer_tree_impl_(nullptr) {} ScrollState::ScrollState(const ScrollState& other) = default; diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc index 23abc3b..7f51dc0 100644 --- a/cc/layers/layer.cc +++ b/cc/layers/layer.cc @@ -884,6 +884,10 @@ void Layer::SetScrollOffset(const gfx::ScrollOffset& scroll_offset) { if (!layer_tree_host_) return; + if (scroll_tree_index() != -1 && scrollable()) + layer_tree_host_->property_trees()->scroll_tree.SetScrollOffset( + id(), scroll_offset); + if (TransformNode* transform_node = layer_tree_host_->property_trees()->transform_tree.Node( transform_tree_index())) { @@ -923,6 +927,11 @@ void Layer::SetScrollOffsetFromImplSide( SetNeedsPushProperties(); bool needs_rebuild = true; + + if (scroll_tree_index() != -1 && scrollable()) + layer_tree_host_->property_trees()->scroll_tree.SetScrollOffset( + id(), scroll_offset); + if (TransformNode* transform_node = layer_tree_host_->property_trees()->transform_tree.Node( transform_tree_index())) { @@ -1338,9 +1347,10 @@ void Layer::PushPropertiesTo(LayerImpl* layer) { // active tree. To do so, avoid scrolling the pending tree along with it // instead of trying to undo that scrolling later. if (ScrollOffsetAnimationWasInterrupted()) - layer->PushScrollOffsetFromMainThreadAndClobberActiveValue(scroll_offset_); - else - layer->PushScrollOffsetFromMainThread(scroll_offset_); + layer_tree_host() + ->property_trees() + ->scroll_tree.synced_scroll_offset(layer->id()) + ->set_clobber_active_value(); layer->SetScrollCompensationAdjustment(ScrollCompensationAdjustment()); { @@ -1703,8 +1713,7 @@ void Layer::FromLayerSpecificPropertiesProto( } scoped_ptr<LayerImpl> Layer::CreateLayerImpl(LayerTreeImpl* tree_impl) { - return LayerImpl::Create(tree_impl, layer_id_, - new LayerImpl::SyncedScrollOffset); + return LayerImpl::Create(tree_impl, layer_id_); } bool Layer::DrawsContent() const { diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc index a16baa5..5d31a22 100644 --- a/cc/layers/layer_impl.cc +++ b/cc/layers/layer_impl.cc @@ -43,13 +43,7 @@ #include "ui/gfx/geometry/vector2d_conversions.h" namespace cc { -LayerImpl::LayerImpl(LayerTreeImpl* layer_impl, int id) - : LayerImpl(layer_impl, id, new LayerImpl::SyncedScrollOffset) { -} - -LayerImpl::LayerImpl(LayerTreeImpl* tree_impl, - int id, - scoped_refptr<SyncedScrollOffset> scroll_offset) +LayerImpl::LayerImpl(LayerTreeImpl* tree_impl, int id) : parent_(nullptr), scroll_parent_(nullptr), clip_parent_(nullptr), @@ -57,7 +51,6 @@ LayerImpl::LayerImpl(LayerTreeImpl* tree_impl, replica_layer_id_(-1), layer_id_(id), layer_tree_impl_(tree_impl), - scroll_offset_(scroll_offset), scroll_clip_layer_id_(Layer::INVALID_ID), main_thread_scrolling_reasons_( MainThreadScrollingReason::kNotScrollingOnMain), @@ -490,17 +483,12 @@ bool LayerImpl::user_scrollable(ScrollbarOrientation orientation) const { : user_scrollable_vertical_; } -void LayerImpl::ApplySentScrollDeltasFromAbortedCommit() { - DCHECK(layer_tree_impl()->IsActiveTree()); - scroll_offset_->AbortCommit(); -} - skia::RefPtr<SkPicture> LayerImpl::GetPicture() { return skia::RefPtr<SkPicture>(); } scoped_ptr<LayerImpl> LayerImpl::CreateLayerImpl(LayerTreeImpl* tree_impl) { - return LayerImpl::Create(tree_impl, layer_id_, scroll_offset_); + return LayerImpl::Create(tree_impl, layer_id_); } void LayerImpl::set_main_thread_scrolling_reasons( @@ -573,8 +561,6 @@ void LayerImpl::PushPropertiesTo(LayerImpl* layer) { layer->SetScrollCompensationAdjustment(scroll_compensation_adjustment_); - layer->PushScrollOffset(nullptr); - layer->Set3dSortingContextId(sorting_context_id_); layer->SetNumDescendantsThatDrawContent(num_descendants_that_draw_content_); @@ -1302,6 +1288,16 @@ void LayerImpl::GatherFrameTimingRequestIds(std::vector<int64_t>* request_ids) { request_ids->push_back(request.id()); } +const SyncedScrollOffset* LayerImpl::synced_scroll_offset() const { + return layer_tree_impl()->property_trees()->scroll_tree.synced_scroll_offset( + id()); +} + +SyncedScrollOffset* LayerImpl::synced_scroll_offset() { + return layer_tree_impl()->property_trees()->scroll_tree.synced_scroll_offset( + id()); +} + void LayerImpl::SetTransform(const gfx::Transform& transform) { if (transform_ == transform) return; @@ -1446,74 +1442,45 @@ void LayerImpl::AddDamageRect(const gfx::Rect& damage_rect) { void LayerImpl::SetCurrentScrollOffset(const gfx::ScrollOffset& scroll_offset) { DCHECK(IsActive()); - if (scroll_offset_->SetCurrent(scroll_offset)) + if (synced_scroll_offset()->SetCurrent(scroll_offset)) DidUpdateScrollOffset(); } -void LayerImpl::PushScrollOffsetFromMainThread( - const gfx::ScrollOffset& scroll_offset) { - PushScrollOffset(&scroll_offset); -} - -void LayerImpl::PushScrollOffsetFromMainThreadAndClobberActiveValue( - const gfx::ScrollOffset& scroll_offset) { - scroll_offset_->set_clobber_active_value(); - PushScrollOffset(&scroll_offset); -} - -gfx::ScrollOffset LayerImpl::PullDeltaForMainThread() { - // TODO(miletus): Remove all this temporary flooring machinery when - // Blink fully supports fractional scrolls. - gfx::ScrollOffset current_offset = CurrentScrollOffset(); - gfx::ScrollOffset current_delta = IsActive() - ? scroll_offset_->Delta() - : scroll_offset_->PendingDelta().get(); - gfx::ScrollOffset floored_delta(floor(current_delta.x()), - floor(current_delta.y())); - gfx::ScrollOffset diff_delta = floored_delta - current_delta; - gfx::ScrollOffset tmp_offset = current_offset + diff_delta; - scroll_offset_->SetCurrent(tmp_offset); - gfx::ScrollOffset delta = scroll_offset_->PullDeltaForMainThread(); - scroll_offset_->SetCurrent(current_offset); - return delta; -} - gfx::ScrollOffset LayerImpl::CurrentScrollOffset() const { - return scroll_offset_->Current(IsActive()); + return synced_scroll_offset()->Current(IsActive()); } gfx::Vector2dF LayerImpl::ScrollDelta() const { if (IsActive()) - return gfx::Vector2dF(scroll_offset_->Delta().x(), - scroll_offset_->Delta().y()); + return gfx::Vector2dF(synced_scroll_offset()->Delta().x(), + synced_scroll_offset()->Delta().y()); else - return gfx::Vector2dF(scroll_offset_->PendingDelta().get().x(), - scroll_offset_->PendingDelta().get().y()); + return gfx::Vector2dF(synced_scroll_offset()->PendingDelta().get().x(), + synced_scroll_offset()->PendingDelta().get().y()); } void LayerImpl::SetScrollDelta(const gfx::Vector2dF& delta) { DCHECK(IsActive()); DCHECK(scrollable() || delta.IsZero()); - SetCurrentScrollOffset(scroll_offset_->ActiveBase() + + SetCurrentScrollOffset(synced_scroll_offset()->ActiveBase() + gfx::ScrollOffset(delta)); } gfx::ScrollOffset LayerImpl::BaseScrollOffset() const { if (IsActive()) - return scroll_offset_->ActiveBase(); + return synced_scroll_offset()->ActiveBase(); else - return scroll_offset_->PendingBase(); + return synced_scroll_offset()->PendingBase(); } -void LayerImpl::PushScrollOffset(const gfx::ScrollOffset* scroll_offset) { - DCHECK(scroll_offset || IsActive()); +void LayerImpl::PushScrollOffsetFromMainThread( + const gfx::ScrollOffset& scroll_offset) { bool changed = false; - if (scroll_offset) { - DCHECK(!IsActive() || !layer_tree_impl_->FindPendingTreeLayerById(id())); - changed |= scroll_offset_->PushFromMainThread(*scroll_offset); - } + DCHECK(!IsActive() || !layer_tree_impl_->FindPendingTreeLayerById(id())); + changed |= synced_scroll_offset()->PushFromMainThread(scroll_offset); + if (IsActive()) { - changed |= scroll_offset_->PushPendingToActive(); + changed |= synced_scroll_offset()->PushPendingToActive(); } if (changed) @@ -1527,7 +1494,8 @@ void LayerImpl::UpdatePropertyTreeScrollOffset() { TransformTree& transform_tree = layer_tree_impl()->property_trees()->transform_tree; TransformNode* node = transform_tree.Node(transform_tree_index_); - gfx::ScrollOffset current_offset = scroll_offset_->Current(IsActive()); + gfx::ScrollOffset current_offset = + synced_scroll_offset()->Current(IsActive()); if (node->data.scroll_offset != current_offset) { node->data.scroll_offset = current_offset; node->data.needs_local_transform_update = true; @@ -1537,8 +1505,6 @@ void LayerImpl::UpdatePropertyTreeScrollOffset() { } void LayerImpl::DidUpdateScrollOffset() { - DCHECK(scroll_offset_); - layer_tree_impl()->DidUpdateScrollState(id()); if (transform_tree_index_ != -1) { @@ -1653,10 +1619,11 @@ void LayerImpl::AsValueInto(base::trace_event::TracedValue* state) const { state->SetInteger("mutable_properties", mutable_properties_); } - MathUtil::AddToTracedValue( - "scroll_offset", scroll_offset_ ? scroll_offset_->Current(IsActive()) - : gfx::ScrollOffset(), - state); + MathUtil::AddToTracedValue("scroll_offset", + synced_scroll_offset() + ? synced_scroll_offset()->Current(IsActive()) + : gfx::ScrollOffset(), + state); MathUtil::AddToTracedValue("transform_origin", transform_origin_, state); diff --git a/cc/layers/layer_impl.h b/cc/layers/layer_impl.h index f0e14a7..f3e4aca 100644 --- a/cc/layers/layer_impl.h +++ b/cc/layers/layer_impl.h @@ -83,20 +83,12 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver, public LayerAnimationValueProvider, public AnimationDelegate { public: - typedef SyncedProperty<AdditionGroup<gfx::ScrollOffset>> SyncedScrollOffset; typedef LayerImplList RenderSurfaceListType; typedef LayerImplList LayerListType; typedef RenderSurfaceImpl RenderSurfaceType; enum RenderingContextConstants { NO_RENDERING_CONTEXT = 0 }; - static scoped_ptr<LayerImpl> Create( - LayerTreeImpl* tree_impl, - int id, - scoped_refptr<SyncedScrollOffset> scroll_offset) { - return make_scoped_ptr(new LayerImpl(tree_impl, id, scroll_offset)); - } - static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) { return make_scoped_ptr(new LayerImpl(tree_impl, id)); } @@ -460,13 +452,12 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver, gfx::Vector2dF bounds_delta() const { return bounds_delta_; } void SetCurrentScrollOffset(const gfx::ScrollOffset& scroll_offset); + // must only be called by tests when updating scroll offset of a single layer, + // the standard process to update scroll offsets is to call + // ScrollTree::UpdateScrollOffsetMap() which updates scroll offsets of all + // layers. void PushScrollOffsetFromMainThread(const gfx::ScrollOffset& scroll_offset); - // This method is similar to PushScrollOffsetFromMainThread but will cause the - // scroll offset given to clobber any scroll changes on the active tree in the - // time until this value is pushed to the active tree. - void PushScrollOffsetFromMainThreadAndClobberActiveValue( - const gfx::ScrollOffset& scroll_offset); - gfx::ScrollOffset PullDeltaForMainThread(); + gfx::ScrollOffset CurrentScrollOffset() const; gfx::ScrollOffset BaseScrollOffset() const; gfx::Vector2dF ScrollDelta() const; @@ -504,8 +495,6 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver, bool user_scrollable(ScrollbarOrientation orientation) const; - void ApplySentScrollDeltasFromAbortedCommit(); - void set_main_thread_scrolling_reasons( uint32_t main_thread_scrolling_reasons); uint32_t main_thread_scrolling_reasons() const { @@ -634,7 +623,8 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver, } void GatherFrameTimingRequestIds(std::vector<int64_t>* request_ids); - SyncedScrollOffset* synced_scroll_offset() { return scroll_offset_.get(); } + const SyncedScrollOffset* synced_scroll_offset() const; + SyncedScrollOffset* synced_scroll_offset(); // Get the correct invalidation region instead of conservative Rect // for layers that provide it. @@ -684,6 +674,7 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver, } void NoteLayerPropertyChanged(); + void DidUpdateScrollOffset(); void PushLayerPropertyChangedForSubtree(); @@ -712,8 +703,6 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver, private: void ValidateQuadResourcesInternal(DrawQuad* quad) const; - void PushScrollOffset(const gfx::ScrollOffset* scroll_offset); - void DidUpdateScrollOffset(); void NoteLayerPropertyChangedForDescendantsInternal(); void PushLayerPropertyChangedForSubtreeInternal(); @@ -743,8 +732,6 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver, int layer_id_; LayerTreeImpl* layer_tree_impl_; - // Properties dynamically changeable on active tree. - scoped_refptr<SyncedScrollOffset> scroll_offset_; gfx::Vector2dF bounds_delta_; // Properties synchronized from the associated Layer. diff --git a/cc/layers/layer_impl_unittest.cc b/cc/layers/layer_impl_unittest.cc index d804c57..a8336d8 100644 --- a/cc/layers/layer_impl_unittest.cc +++ b/cc/layers/layer_impl_unittest.cc @@ -337,8 +337,7 @@ TEST(LayerImplTest, VerifyNeedsUpdateDrawProperties) { layer->SetScrollDelta(arbitrary_vector2d)); VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(layer->PushScrollOffsetFromMainThread( gfx::ScrollOffset(arbitrary_vector2d))); - VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES(layer->PushScrollOffsetFromMainThread( - gfx::ScrollOffset(arbitrary_vector2d))); + VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(layer->DidUpdateScrollOffset()); // Unrelated functions, always set to new values, always set needs update. VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES( @@ -570,7 +569,7 @@ TEST_F(LayerImplScrollTest, ApplySentScrollsNoListener) { layer()->PushScrollOffsetFromMainThread(scroll_offset); layer()->ScrollBy(sent_scroll_delta); - layer()->PullDeltaForMainThread(); + layer()->synced_scroll_offset()->PullDeltaForMainThread(); layer()->SetCurrentScrollOffset(scroll_offset + gfx::ScrollOffset(scroll_delta)); @@ -579,7 +578,7 @@ TEST_F(LayerImplScrollTest, ApplySentScrollsNoListener) { EXPECT_VECTOR_EQ(scroll_delta, layer()->ScrollDelta()); EXPECT_VECTOR_EQ(scroll_offset, layer()->BaseScrollOffset()); - layer()->ApplySentScrollDeltasFromAbortedCommit(); + layer()->synced_scroll_offset()->AbortCommit(); EXPECT_VECTOR_EQ(gfx::ScrollOffsetWithDelta(scroll_offset, scroll_delta), layer()->CurrentScrollOffset()); @@ -612,10 +611,10 @@ TEST_F(LayerImplScrollTest, PushPropertiesToMirrorsCurrentScrollOffset) { EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), unscrolled); EXPECT_VECTOR_EQ(gfx::Vector2dF(22, 23), layer()->CurrentScrollOffset()); - layer()->PullDeltaForMainThread(); + layer()->synced_scroll_offset()->PullDeltaForMainThread(); - scoped_ptr<LayerImpl> pending_layer = LayerImpl::Create( - host_impl().sync_tree(), layer()->id(), layer()->synced_scroll_offset()); + scoped_ptr<LayerImpl> pending_layer = + LayerImpl::Create(host_impl().sync_tree(), layer()->id()); pending_layer->PushScrollOffsetFromMainThread(layer()->CurrentScrollOffset()); pending_layer->PushPropertiesTo(layer()); diff --git a/cc/layers/layer_iterator_unittest.cc b/cc/layers/layer_iterator_unittest.cc index b9b3cf3..158dd93 100644 --- a/cc/layers/layer_iterator_unittest.cc +++ b/cc/layers/layer_iterator_unittest.cc @@ -35,7 +35,7 @@ class TestLayerImpl : public LayerImpl { private: explicit TestLayerImpl(LayerTreeImpl* tree, int id) - : LayerImpl(tree, id, new SyncedScrollOffset), + : LayerImpl(tree, id), count_representing_target_surface_(-1), count_representing_contributing_surface_(-1), count_representing_itself_(-1) { diff --git a/cc/layers/picture_image_layer_impl.cc b/cc/layers/picture_image_layer_impl.cc index 03ef5ae..c816986 100644 --- a/cc/layers/picture_image_layer_impl.cc +++ b/cc/layers/picture_image_layer_impl.cc @@ -14,11 +14,7 @@ namespace cc { PictureImageLayerImpl::PictureImageLayerImpl(LayerTreeImpl* tree_impl, int id, bool is_mask) - : PictureLayerImpl(tree_impl, - id, - is_mask, - new LayerImpl::SyncedScrollOffset) { -} + : PictureLayerImpl(tree_impl, id, is_mask) {} PictureImageLayerImpl::~PictureImageLayerImpl() { } diff --git a/cc/layers/picture_layer.cc b/cc/layers/picture_layer.cc index afb62c0..f528516 100644 --- a/cc/layers/picture_layer.cc +++ b/cc/layers/picture_layer.cc @@ -45,8 +45,7 @@ PictureLayer::~PictureLayer() { } scoped_ptr<LayerImpl> PictureLayer::CreateLayerImpl(LayerTreeImpl* tree_impl) { - return PictureLayerImpl::Create(tree_impl, id(), is_mask_, - new LayerImpl::SyncedScrollOffset); + return PictureLayerImpl::Create(tree_impl, id(), is_mask_); } void PictureLayer::PushPropertiesTo(LayerImpl* base_layer) { diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc index 7688b97..076ee23 100644 --- a/cc/layers/picture_layer_impl.cc +++ b/cc/layers/picture_layer_impl.cc @@ -59,12 +59,10 @@ const int kTileMinimalAlignment = 4; namespace cc { -PictureLayerImpl::PictureLayerImpl( - LayerTreeImpl* tree_impl, - int id, - bool is_mask, - scoped_refptr<SyncedScrollOffset> scroll_offset) - : LayerImpl(tree_impl, id, scroll_offset), +PictureLayerImpl::PictureLayerImpl(LayerTreeImpl* tree_impl, + int id, + bool is_mask) + : LayerImpl(tree_impl, id), twin_layer_(nullptr), tilings_(CreatePictureLayerTilingSet()), ideal_page_scale_(0.f), @@ -95,8 +93,7 @@ const char* PictureLayerImpl::LayerTypeAsString() const { scoped_ptr<LayerImpl> PictureLayerImpl::CreateLayerImpl( LayerTreeImpl* tree_impl) { - return PictureLayerImpl::Create(tree_impl, id(), is_mask_, - synced_scroll_offset()); + return PictureLayerImpl::Create(tree_impl, id(), is_mask_); } void PictureLayerImpl::PushPropertiesTo(LayerImpl* base_layer) { diff --git a/cc/layers/picture_layer_impl.h b/cc/layers/picture_layer_impl.h index 03316dcd..50abaa8 100644 --- a/cc/layers/picture_layer_impl.h +++ b/cc/layers/picture_layer_impl.h @@ -30,13 +30,10 @@ class CC_EXPORT PictureLayerImpl : public LayerImpl, NON_EXPORTED_BASE(public PictureLayerTilingClient) { public: - static scoped_ptr<PictureLayerImpl> Create( - LayerTreeImpl* tree_impl, - int id, - bool is_mask, - scoped_refptr<SyncedScrollOffset> scroll_offset) { - return make_scoped_ptr( - new PictureLayerImpl(tree_impl, id, is_mask, scroll_offset)); + static scoped_ptr<PictureLayerImpl> Create(LayerTreeImpl* tree_impl, + int id, + bool is_mask) { + return make_scoped_ptr(new PictureLayerImpl(tree_impl, id, is_mask)); } ~PictureLayerImpl() override; @@ -103,10 +100,7 @@ class CC_EXPORT PictureLayerImpl friend class LayerRasterTileIterator; using TileRequirementCheck = bool (PictureLayerTiling::*)(const Tile*) const; - PictureLayerImpl(LayerTreeImpl* tree_impl, - int id, - bool is_mask, - scoped_refptr<SyncedScrollOffset> scroll_offset); + PictureLayerImpl(LayerTreeImpl* tree_impl, int id, bool is_mask); PictureLayerTiling* AddTiling(float contents_scale); void RemoveAllTilings(); void AddTilingsForRasterScale(); diff --git a/cc/layers/picture_layer_impl_unittest.cc b/cc/layers/picture_layer_impl_unittest.cc index f132b3f..67a00a1 100644 --- a/cc/layers/picture_layer_impl_unittest.cc +++ b/cc/layers/picture_layer_impl_unittest.cc @@ -239,6 +239,7 @@ class PictureLayerImplTest : public testing::Test { if (!tile_size.IsEmpty()) pending_layer->set_fixed_tile_size(tile_size); pending_layer->SetDrawsContent(true); + pending_layer->SetScrollClipLayer(pending_root->id()); } else { pending_layer.reset(static_cast<FakePictureLayerImpl*>( pending_root->RemoveChild(pending_root->children()[0].get()) diff --git a/cc/layers/scrollbar_layer_unittest.cc b/cc/layers/scrollbar_layer_unittest.cc index d7beffb..ee41989 100644 --- a/cc/layers/scrollbar_layer_unittest.cc +++ b/cc/layers/scrollbar_layer_unittest.cc @@ -219,6 +219,7 @@ TEST_F(ScrollbarLayerTest, ScrollOffsetSynchronization) { layer_tree_root->SavePaintProperties(); content_layer->SavePaintProperties(); + layer_tree_host_->UpdateLayers(); LayerImpl* layer_impl_tree_root = layer_tree_host_->CommitAndCreateLayerImplTree(); @@ -330,6 +331,7 @@ TEST_F(ScrollbarLayerTest, ThumbRect) { scrollbar_layer->fake_scrollbar()->set_track_rect(gfx::Rect(30, 10, 50, 10)); scrollbar_layer->fake_scrollbar()->set_thumb_thickness(10); scrollbar_layer->fake_scrollbar()->set_thumb_length(4); + layer_tree_host_->UpdateLayers(); LayerImpl* root_clip_layer_impl = nullptr; LayerImpl* root_layer_impl = nullptr; PaintedScrollbarLayerImpl* scrollbar_layer_impl = nullptr; diff --git a/cc/proto/BUILD.gn b/cc/proto/BUILD.gn index f06e869..4387941 100644 --- a/cc/proto/BUILD.gn +++ b/cc/proto/BUILD.gn @@ -58,6 +58,7 @@ proto_library("proto_internal") { "skregion.proto", "skrrect.proto", "skxfermode.proto", + "synced_property.proto", "transform.proto", "vector2d.proto", "vector2df.proto", diff --git a/cc/proto/property_tree.proto b/cc/proto/property_tree.proto index a91824c..d8e8fae 100644 --- a/cc/proto/property_tree.proto +++ b/cc/proto/property_tree.proto @@ -7,6 +7,7 @@ syntax = "proto2"; import "rectf.proto"; import "scroll_offset.proto"; import "size.proto"; +import "synced_property.proto"; import "transform.proto"; import "vector2df.proto"; @@ -156,9 +157,15 @@ message PropertyTree { optional ScrollTreeData scroll_tree_data = 1001; } +message ScrollOffsetMapEntry { + required int64 layer_id = 1; + optional SyncedProperty scroll_offset = 2; +} + // Proto for data members of class ScrollTree message ScrollTreeData { optional int64 currently_scrolling_node_id = 1; + repeated ScrollOffsetMapEntry layer_id_to_scroll_offset_map = 2; } // Proto for data members of class TransformTree. @@ -174,7 +181,7 @@ message TransformTreeData { } // Proto for class PropertyTrees. -// NEXT ID: 13 +// NEXT ID: 14 message PropertyTrees { optional PropertyTree transform_tree = 1; optional PropertyTree effect_tree = 2; @@ -186,6 +193,8 @@ message PropertyTrees { optional bool changed = 11; optional bool full_tree_damaged = 12; optional int64 sequence_number = 6; + optional bool is_main_thread = 13; + optional bool is_active = 14; optional Vector2dF inner_viewport_container_bounds_delta = 8; optional Vector2dF outer_viewport_container_bounds_delta = 9; diff --git a/cc/proto/synced_property.proto b/cc/proto/synced_property.proto new file mode 100644 index 0000000..5b8658f --- /dev/null +++ b/cc/proto/synced_property.proto @@ -0,0 +1,29 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +syntax = "proto2"; + +import "scroll_offset.proto"; + +option optimize_for = LITE_RUNTIME; + +package cc.proto; + +// Since plumbing SyncedScrollOffset is only used by PropertyTree, and can only +// travel from main thread to impl thread one way, the From/To protobuf function +// for SyncedProperty only needs to care the current base, because main thread +// does not have pending/active tree or scroll offset deltas. +message ScrollOffsetGroup { + optional ScrollOffset pending_base = 1; + optional ScrollOffset pending_delta = 2; + optional ScrollOffset active_base = 3; + optional ScrollOffset active_delta = 4; + optional ScrollOffset sent_delta = 5; +} + +message SyncedProperty { + optional bool clobber_active_value = 1; + + optional ScrollOffsetGroup scroll_offset_group = 1001; +} diff --git a/cc/proto/synced_property_conversions.cc b/cc/proto/synced_property_conversions.cc new file mode 100644 index 0000000..09c8be2 --- /dev/null +++ b/cc/proto/synced_property_conversions.cc @@ -0,0 +1,26 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/proto/synced_property_conversions.h" + +#include "cc/proto/gfx_conversions.h" +#include "cc/proto/synced_property.pb.h" + +namespace cc { + +void SyncedScrollOffsetToProto(const SyncedScrollOffset& synced_scroll_offset, + proto::SyncedProperty* proto) { + proto::ScrollOffsetGroup* data = proto->mutable_scroll_offset_group(); + ScrollOffsetToProto(synced_scroll_offset.PendingBase(), + data->mutable_pending_base()); +} + +void ProtoToSyncedScrollOffset(const proto::SyncedProperty& proto, + SyncedScrollOffset* synced_scroll_offset) { + const proto::ScrollOffsetGroup& data = proto.scroll_offset_group(); + synced_scroll_offset->PushFromMainThread( + ProtoToScrollOffset(data.pending_base())); +} + +} // namespace cc diff --git a/cc/proto/synced_property_conversions.h b/cc/proto/synced_property_conversions.h new file mode 100644 index 0000000..7f3c623 --- /dev/null +++ b/cc/proto/synced_property_conversions.h @@ -0,0 +1,26 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_PROTO_SYNCED_PROPERTY_CONVERSIONS_H_ +#define CC_PROTO_SYNCED_PROPERTY_CONVERSIONS_H_ + +#include "cc/base/cc_export.h" +#include "cc/trees/property_tree.h" + +namespace cc { + +namespace proto { +class SyncedProperty; +} // namespace proto + +CC_EXPORT void SyncedScrollOffsetToProto( + const SyncedScrollOffset& synced_scroll_offset, + proto::SyncedProperty* proto); +CC_EXPORT void ProtoToSyncedScrollOffset( + const proto::SyncedProperty& proto, + SyncedScrollOffset* synced_scroll_offset); + +} // namespace cc + +#endif // CC_PROTO_SYNCED_PROPERTY_CONVERSIONS_H_ diff --git a/cc/proto/synced_property_conversions_unittest.cc b/cc/proto/synced_property_conversions_unittest.cc new file mode 100644 index 0000000..bf2a4fd --- /dev/null +++ b/cc/proto/synced_property_conversions_unittest.cc @@ -0,0 +1,30 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/proto/synced_property_conversions.h" + +#include "cc/proto/synced_property.pb.h" +#include "cc/trees/property_tree.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace cc { +namespace { + +TEST(SyncedPropertyConversionTest, SerializeDeserializeSyncedScrollOffset) { + scoped_refptr<SyncedScrollOffset> synced_scroll_offset = + new SyncedScrollOffset(); + synced_scroll_offset->PushFromMainThread(gfx::ScrollOffset(1, 2)); + proto::SyncedProperty proto; + scoped_refptr<SyncedScrollOffset> serialized_synced_scroll_offset = + new SyncedScrollOffset(); + SyncedScrollOffsetToProto(*synced_scroll_offset.get(), &proto); + ProtoToSyncedScrollOffset(proto, serialized_synced_scroll_offset.get()); + EXPECT_EQ(synced_scroll_offset.get()->PendingBase(), + serialized_synced_scroll_offset.get()->PendingBase()); + EXPECT_EQ(synced_scroll_offset.get()->PendingBase(), + serialized_synced_scroll_offset.get()->PendingBase()); +} + +} // namespace +} // namespace cc diff --git a/cc/test/fake_layer_tree_host.cc b/cc/test/fake_layer_tree_host.cc index 8d2a0f2..5125a7b 100644 --- a/cc/test/fake_layer_tree_host.cc +++ b/cc/test/fake_layer_tree_host.cc @@ -91,6 +91,7 @@ LayerImpl* FakeLayerTreeHost::CommitAndCreateLayerImplTree() { TreeSynchronizer::PushProperties(root_layer(), layer_impl.get()); active_tree()->SetRootLayer(std::move(layer_impl)); + active_tree()->UpdatePropertyTreeScrollOffset(property_trees()); if (page_scale_layer() && inner_viewport_scroll_layer()) { active_tree()->SetViewportLayersFromIds( @@ -114,6 +115,7 @@ LayerImpl* FakeLayerTreeHost::CommitAndCreatePendingTree() { TreeSynchronizer::PushProperties(root_layer(), layer_impl.get()); pending_tree()->SetRootLayer(std::move(layer_impl)); + pending_tree()->UpdatePropertyTreeScrollOffset(property_trees()); return pending_tree()->root_layer(); } diff --git a/cc/test/fake_picture_layer_impl.cc b/cc/test/fake_picture_layer_impl.cc index 225ee64..cffed1c 100644 --- a/cc/test/fake_picture_layer_impl.cc +++ b/cc/test/fake_picture_layer_impl.cc @@ -17,10 +17,7 @@ FakePictureLayerImpl::FakePictureLayerImpl( int id, scoped_refptr<DisplayListRasterSource> raster_source, bool is_mask) - : PictureLayerImpl(tree_impl, - id, - is_mask, - new LayerImpl::SyncedScrollOffset), + : PictureLayerImpl(tree_impl, id, is_mask), append_quads_count_(0), did_become_active_call_count_(0), has_valid_tile_priorities_(false), @@ -36,10 +33,7 @@ FakePictureLayerImpl::FakePictureLayerImpl( scoped_refptr<DisplayListRasterSource> raster_source, bool is_mask, const gfx::Size& layer_bounds) - : PictureLayerImpl(tree_impl, - id, - is_mask, - new LayerImpl::SyncedScrollOffset), + : PictureLayerImpl(tree_impl, id, is_mask), append_quads_count_(0), did_become_active_call_count_(0), has_valid_tile_priorities_(false), @@ -52,29 +46,16 @@ FakePictureLayerImpl::FakePictureLayerImpl( FakePictureLayerImpl::FakePictureLayerImpl(LayerTreeImpl* tree_impl, int id, bool is_mask) - : FakePictureLayerImpl(tree_impl, - id, - is_mask, - new LayerImpl::SyncedScrollOffset) { -} - -FakePictureLayerImpl::FakePictureLayerImpl( - LayerTreeImpl* tree_impl, - int id, - bool is_mask, - scoped_refptr<LayerImpl::SyncedScrollOffset> synced_scroll_offset) - : PictureLayerImpl(tree_impl, id, is_mask, synced_scroll_offset), + : PictureLayerImpl(tree_impl, id, is_mask), append_quads_count_(0), did_become_active_call_count_(0), has_valid_tile_priorities_(false), use_set_valid_tile_priorities_flag_(false), - release_resources_count_(0) { -} + release_resources_count_(0) {} scoped_ptr<LayerImpl> FakePictureLayerImpl::CreateLayerImpl( LayerTreeImpl* tree_impl) { - return make_scoped_ptr(new FakePictureLayerImpl(tree_impl, id(), is_mask_, - synced_scroll_offset())); + return make_scoped_ptr(new FakePictureLayerImpl(tree_impl, id(), is_mask_)); } void FakePictureLayerImpl::PushPropertiesTo(LayerImpl* layer_impl) { diff --git a/cc/test/fake_picture_layer_impl.h b/cc/test/fake_picture_layer_impl.h index fcc4946..2ba9761 100644 --- a/cc/test/fake_picture_layer_impl.h +++ b/cc/test/fake_picture_layer_impl.h @@ -157,11 +157,6 @@ class FakePictureLayerImpl : public PictureLayerImpl { bool is_mask, const gfx::Size& layer_bounds); FakePictureLayerImpl(LayerTreeImpl* tree_impl, int id, bool is_mask); - FakePictureLayerImpl( - LayerTreeImpl* tree_impl, - int id, - bool is_mask, - scoped_refptr<LayerImpl::SyncedScrollOffset> synced_scroll_offset); private: gfx::Size fixed_tile_size_; diff --git a/cc/tiles/tile_manager_unittest.cc b/cc/tiles/tile_manager_unittest.cc index 3dd1453..1060edc 100644 --- a/cc/tiles/tile_manager_unittest.cc +++ b/cc/tiles/tile_manager_unittest.cc @@ -1481,7 +1481,7 @@ TEST_F(TileManagerTilePriorityQueueTest, NoRasterTasksforSolidColorTiles) { tiling_client.SetTileSize(size); scoped_ptr<PictureLayerImpl> layer_impl = - PictureLayerImpl::Create(host_impl_.active_tree(), 1, false, nullptr); + PictureLayerImpl::Create(host_impl_.active_tree(), 1, false); PictureLayerTilingSet* tiling_set = layer_impl->picture_layer_tiling_set(); PictureLayerTiling* tiling = tiling_set->AddTiling(1.0f, raster_source); @@ -1700,7 +1700,7 @@ TEST_F(TileManagerTest, LowResHasNoImage) { tiling_client.SetTileSize(size); scoped_ptr<PictureLayerImpl> layer = - PictureLayerImpl::Create(host_impl_->active_tree(), 1, false, nullptr); + PictureLayerImpl::Create(host_impl_->active_tree(), 1, false); PictureLayerTilingSet* tiling_set = layer->picture_layer_tiling_set(); auto* tiling = tiling_set->AddTiling(1.0f, raster); diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc index 268e93b..d5f9b58 100644 --- a/cc/trees/layer_tree_host.cc +++ b/cc/trees/layer_tree_host.cc @@ -495,6 +495,10 @@ void LayerTreeHost::FinishCommitOnImplThread(LayerTreeHostImpl* host_impl) { // properties, which updates property tree indices. sync_tree->UpdatePropertyTreeScrollingAndAnimationFromMainThread(); + // This must happen after synchronizing property trees and after pushing + // properties, which updates the clobber_active_value flag. + sync_tree->UpdatePropertyTreeScrollOffset(&property_trees_); + micro_benchmark_controller_.ScheduleImplBenchmarks(host_impl); // We don't track changes to effect tree on main thread. But, to preserve any // change tracking done on active tree's effect tree, we copy it to the main diff --git a/cc/trees/layer_tree_host_common_unittest.cc b/cc/trees/layer_tree_host_common_unittest.cc index fae38ae..d2c1f55 100644 --- a/cc/trees/layer_tree_host_common_unittest.cc +++ b/cc/trees/layer_tree_host_common_unittest.cc @@ -10056,7 +10056,8 @@ TEST_F(LayerTreeHostCommonTest, ScrollTreeBuilderTest) { // Property tree root ScrollTree scroll_tree = host()->property_trees()->scroll_tree; - ScrollTree expected_scroll_tree; + PropertyTrees property_trees; + ScrollTree expected_scroll_tree = property_trees.scroll_tree; ScrollNode* property_tree_root = expected_scroll_tree.Node(0); property_tree_root->id = kRootPropertyTreeNodeId; property_tree_root->parent_id = kInvalidPropertyTreeNodeId; @@ -10139,6 +10140,12 @@ TEST_F(LayerTreeHostCommonTest, ScrollTreeBuilderTest) { scroll_parent5.data.transform_id = parent5->transform_tree_index(); expected_scroll_tree.Insert(scroll_parent5, 1); + expected_scroll_tree.synced_scroll_offset(parent2->id()) + ->PushFromMainThread(gfx::ScrollOffset(0, 0)); + expected_scroll_tree.synced_scroll_offset(child7->id()) + ->PushFromMainThread(gfx::ScrollOffset(0, 0)); + expected_scroll_tree.synced_scroll_offset(grand_child11->id()) + ->PushFromMainThread(gfx::ScrollOffset(0, 0)); expected_scroll_tree.set_needs_update(false); EXPECT_EQ(expected_scroll_tree, scroll_tree); diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index dfa3c3f..c7bcf2c 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc @@ -3249,16 +3249,9 @@ static void CollectScrollDeltas(ScrollAndScaleSet* scroll_info, if (!root_layer) return; - for (auto* layer : *root_layer->layer_tree_impl()) { - gfx::ScrollOffset scroll_delta = layer->PullDeltaForMainThread(); - - if (!scroll_delta.IsZero()) { - LayerTreeHostCommon::ScrollUpdateInfo scroll; - scroll.layer_id = layer->id(); - scroll.scroll_delta = gfx::Vector2d(scroll_delta.x(), scroll_delta.y()); - scroll_info->scrolls.push_back(scroll); - } - } + return root_layer->layer_tree_impl() + ->property_trees() + ->scroll_tree.CollectScrollDeltas(scroll_info); } scoped_ptr<ScrollAndScaleSet> LayerTreeHostImpl::ProcessScrollDeltas() { diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc index 32e461186..8ecfcdf 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc @@ -2033,7 +2033,7 @@ TEST_F(LayerTreeHostImplTest, PinchGesture) { host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale, max_page_scale); scroll_layer->SetScrollDelta(gfx::Vector2d()); - scroll_layer->PullDeltaForMainThread(); + scroll_layer->synced_scroll_offset()->PullDeltaForMainThread(); scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50)); float page_scale_delta = 0.1f; @@ -2056,7 +2056,7 @@ TEST_F(LayerTreeHostImplTest, PinchGesture) { host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale, max_page_scale); scroll_layer->SetScrollDelta(gfx::Vector2d()); - scroll_layer->PullDeltaForMainThread(); + scroll_layer->synced_scroll_offset()->PullDeltaForMainThread(); scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(20, 20)); float page_scale_delta = 1.f; @@ -2079,7 +2079,7 @@ TEST_F(LayerTreeHostImplTest, PinchGesture) { host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale, max_page_scale); scroll_layer->SetScrollDelta(gfx::Vector2d()); - scroll_layer->PullDeltaForMainThread(); + scroll_layer->synced_scroll_offset()->PullDeltaForMainThread(); scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(20, 20)); float page_scale_delta = 1.f; @@ -2104,7 +2104,7 @@ TEST_F(LayerTreeHostImplTest, PinchGesture) { { host_impl_->active_tree()->PushPageScaleFromMainThread(0.5f, 0.5f, 4.f); scroll_layer->SetScrollDelta(gfx::Vector2d()); - scroll_layer->PullDeltaForMainThread(); + scroll_layer->synced_scroll_offset()->PullDeltaForMainThread(); scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 0)); host_impl_->ScrollBegin(BeginState(gfx::Point(0, 0)).get(), @@ -10192,12 +10192,27 @@ TEST_F(LayerTreeHostImplTest, JitterTest) { LayerTreeImpl* pending_tree = host_impl_->pending_tree(); pending_tree->PushPageScaleFromMainThread(1.f, 1.f, 1.f); + LayerImpl* last_scrolled_layer = pending_tree->LayerById( + host_impl_->active_tree()->LastScrolledLayerId()); + + // When building property trees from impl side, the builder uses the scroll + // offset of layer_impl to initialize the scroll offset in scroll tree: + // scroll_tree.synced_scroll_offset.PushFromMainThread( + // layer->CurrentScrollOffset()). + // However, layer_impl does not store scroll_offset, so it is using scroll + // tree's scroll offset to initialize itself. Usually this approach works + // because this is a simple assignment. However if scroll_offset's pending + // delta is not zero, the delta would be counted twice. + // This hacking here is to restore the damaged scroll offset. + gfx::ScrollOffset pending_base = + last_scrolled_layer->synced_scroll_offset()->PendingBase(); pending_tree->property_trees()->needs_rebuild = true; pending_tree->BuildPropertyTreesForTesting(); + last_scrolled_layer->synced_scroll_offset()->PushFromMainThread( + pending_base); + pending_tree->set_needs_update_draw_properties(); pending_tree->UpdateDrawProperties(false); - LayerImpl* last_scrolled_layer = pending_tree->LayerById( - host_impl_->active_tree()->LastScrolledLayerId()); float jitter = LayerTreeHostCommon::CalculateFrameJitter(last_scrolled_layer); // There should not be any jitter measured till we hit the fixed point hits diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc index 78cd744..89567a5 100644 --- a/cc/trees/layer_tree_impl.cc +++ b/cc/trees/layer_tree_impl.cc @@ -320,6 +320,7 @@ void LayerTreeImpl::PushPropertiesTo(LayerTreeImpl* target_tree) { LayerImpl* layer = target_tree->CurrentlyScrollingLayer(); target_tree->SetPropertyTrees(property_trees_); target_tree->SetCurrentlyScrollingLayer(layer); + target_tree->UpdatePropertyTreeScrollOffset(&property_trees_); if (next_activation_forces_redraw_) { target_tree->ForceRedrawNextActivation(); @@ -687,10 +688,7 @@ void LayerTreeImpl::ApplySentScrollAndScaleDeltasFromAbortedCommit() { if (!root_layer()) return; - LayerTreeHostCommon::CallFunctionForSubtree( - root_layer(), [](LayerImpl* layer) { - layer->ApplySentScrollDeltasFromAbortedCommit(); - }); + property_trees()->scroll_tree.ApplySentScrollDeltasFromAbortedCommit(); } void LayerTreeImpl::SetViewportLayersFromIds( diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h index 07ab83e..9f20b13 100644 --- a/cc/trees/layer_tree_impl.h +++ b/cc/trees/layer_tree_impl.h @@ -135,8 +135,10 @@ class CC_EXPORT LayerTreeImpl { void SetRootLayer(scoped_ptr<LayerImpl>); scoped_ptr<LayerImpl> DetachLayerTree(); - void SetPropertyTrees(const PropertyTrees& property_trees) { + void SetPropertyTrees(const PropertyTrees property_trees) { property_trees_ = property_trees; + property_trees_.is_main_thread = false; + property_trees_.is_active = IsActiveTree(); property_trees_.transform_tree.set_source_to_parent_updates_allowed(false); } PropertyTrees* property_trees() { return &property_trees_; } @@ -216,6 +218,10 @@ class CC_EXPORT LayerTreeImpl { } void UpdatePropertyTreeScrollingAndAnimationFromMainThread(); + void UpdatePropertyTreeScrollOffset(PropertyTrees* property_trees) { + property_trees_.scroll_tree.UpdateScrollOffsetMap( + &property_trees->scroll_tree.scroll_offset_map(), this); + } void SetPageScaleOnActiveTree(float active_page_scale); void PushPageScaleFromMainThread(float page_scale_factor, float min_page_scale_factor, diff --git a/cc/trees/property_tree.cc b/cc/trees/property_tree.cc index 27819d9..4738e01 100644 --- a/cc/trees/property_tree.cc +++ b/cc/trees/property_tree.cc @@ -10,11 +10,15 @@ #include "base/logging.h" #include "cc/base/math_util.h" #include "cc/input/main_thread_scrolling_reason.h" +#include "cc/layers/layer_impl.h" #include "cc/proto/gfx_conversions.h" #include "cc/proto/property_tree.pb.h" #include "cc/proto/scroll_offset.pb.h" +#include "cc/proto/synced_property_conversions.h" #include "cc/proto/transform.pb.h" #include "cc/proto/vector2df.pb.h" +#include "cc/trees/layer_tree_host_common.h" +#include "cc/trees/layer_tree_impl.h" #include "cc/trees/property_tree.h" #include "ui/gfx/geometry/vector2d_conversions.h" @@ -1302,13 +1306,46 @@ void EffectTree::FromProtobuf(const proto::PropertyTree& proto) { PropertyTree::FromProtobuf(proto); } -ScrollTree::ScrollTree() : currently_scrolling_node_id_(-1) {} +ScrollTree::ScrollTree() + : currently_scrolling_node_id_(-1), + layer_id_to_scroll_offset_map_(ScrollTree::ScrollOffsetMap()) {} ScrollTree::~ScrollTree() {} +ScrollTree& ScrollTree::operator=(const ScrollTree& from) { + PropertyTree::operator=(from); + currently_scrolling_node_id_ = -1; + // layer_id_to_scroll_offset_map_ is intentionally omitted in operator=, + // because we do not want to simply copy the map when property tree is + // propagating from pending to active. + // In the main to pending case, we do want to copy it, but this can be done by + // calling UpdateScrollOffsetMap after the assignment; + // In the other case, we want pending and active property trees to share the + // same map. + return *this; +} + bool ScrollTree::operator==(const ScrollTree& other) const { - return PropertyTree::operator==(other) && - CurrentlyScrollingNode() == other.CurrentlyScrollingNode(); + const ScrollTree::ScrollOffsetMap& other_scroll_offset_map = + other.scroll_offset_map(); + if (layer_id_to_scroll_offset_map_.size() != other_scroll_offset_map.size()) + return false; + + for (auto map_entry : layer_id_to_scroll_offset_map_) { + int key = map_entry.first; + if (other_scroll_offset_map.find(key) == other_scroll_offset_map.end() || + map_entry.second != layer_id_to_scroll_offset_map_.at(key)) + return false; + } + + bool is_currently_scrolling_node_equal = + (currently_scrolling_node_id_ == -1) + ? (!other.CurrentlyScrollingNode()) + : (other.CurrentlyScrollingNode() && + currently_scrolling_node_id_ == + other.CurrentlyScrollingNode()->id); + + return PropertyTree::operator==(other) && is_currently_scrolling_node_equal; } void ScrollTree::ToProtobuf(proto::PropertyTree* proto) const { @@ -1319,6 +1356,14 @@ void ScrollTree::ToProtobuf(proto::PropertyTree* proto) const { proto::ScrollTreeData* data = proto->mutable_scroll_tree_data(); data->set_currently_scrolling_node_id(currently_scrolling_node_id_); + for (auto i : layer_id_to_scroll_offset_map_) { + data->add_layer_id_to_scroll_offset_map(); + proto::ScrollOffsetMapEntry* entry = + data->mutable_layer_id_to_scroll_offset_map( + data->layer_id_to_scroll_offset_map_size() - 1); + entry->set_layer_id(i.first); + SyncedScrollOffsetToProto(*i.second.get(), entry->mutable_scroll_offset()); + } } void ScrollTree::FromProtobuf(const proto::PropertyTree& proto) { @@ -1329,6 +1374,24 @@ void ScrollTree::FromProtobuf(const proto::PropertyTree& proto) { const proto::ScrollTreeData& data = proto.scroll_tree_data(); currently_scrolling_node_id_ = data.currently_scrolling_node_id(); + + for (int i = 0; i < data.layer_id_to_scroll_offset_map_size(); ++i) { + const proto::ScrollOffsetMapEntry entry = + data.layer_id_to_scroll_offset_map(i); + layer_id_to_scroll_offset_map_[entry.layer_id()] = new SyncedScrollOffset(); + ProtoToSyncedScrollOffset( + entry.scroll_offset(), + layer_id_to_scroll_offset_map_[entry.layer_id()].get()); + } +} + +void ScrollTree::clear() { + PropertyTree<ScrollNode>::clear(); + + if (property_trees()->is_main_thread) { + currently_scrolling_node_id_ = -1; + layer_id_to_scroll_offset_map_.clear(); + } } gfx::ScrollOffset ScrollTree::MaxScrollOffset(int scroll_node_id) const { @@ -1414,12 +1477,130 @@ gfx::Transform ScrollTree::ScreenSpaceTransform(int scroll_node_id) const { return screen_space_transform; } +// TODO(sunxd): Make this function private once scroll offset access is fully +// directed to scroll tree. +SyncedScrollOffset* ScrollTree::synced_scroll_offset(int layer_id) { + if (layer_id_to_scroll_offset_map_.find(layer_id) == + layer_id_to_scroll_offset_map_.end()) { + layer_id_to_scroll_offset_map_[layer_id] = new SyncedScrollOffset; + } + return layer_id_to_scroll_offset_map_[layer_id].get(); +} + +gfx::ScrollOffset ScrollTree::PullDeltaForMainThread( + SyncedScrollOffset* scroll_offset) { + // TODO(miletus): Remove all this temporary flooring machinery when + // Blink fully supports fractional scrolls. + gfx::ScrollOffset current_offset = + scroll_offset->Current(property_trees()->is_active); + gfx::ScrollOffset current_delta = property_trees()->is_active + ? scroll_offset->Delta() + : scroll_offset->PendingDelta().get(); + gfx::ScrollOffset floored_delta(floor(current_delta.x()), + floor(current_delta.y())); + gfx::ScrollOffset diff_delta = floored_delta - current_delta; + gfx::ScrollOffset tmp_offset = current_offset + diff_delta; + scroll_offset->SetCurrent(tmp_offset); + gfx::ScrollOffset delta = scroll_offset->PullDeltaForMainThread(); + scroll_offset->SetCurrent(current_offset); + return delta; +} + +void ScrollTree::CollectScrollDeltas(ScrollAndScaleSet* scroll_info) { + for (auto map_entry : layer_id_to_scroll_offset_map_) { + gfx::ScrollOffset scroll_delta = + PullDeltaForMainThread(map_entry.second.get()); + + if (!scroll_delta.IsZero()) { + LayerTreeHostCommon::ScrollUpdateInfo scroll; + scroll.layer_id = map_entry.first; + scroll.scroll_delta = gfx::Vector2d(scroll_delta.x(), scroll_delta.y()); + scroll_info->scrolls.push_back(scroll); + } + } +} + +void ScrollTree::UpdateScrollOffsetMapEntry( + int key, + ScrollTree::ScrollOffsetMap* new_scroll_offset_map, + LayerTreeImpl* layer_tree_impl) { + bool changed = false; + // If we are pushing scroll offset from main to pending tree, we create a new + // instance of synced scroll offset; if we are pushing from pending to active, + // we reuse the pending tree's value in the map. + if (!property_trees()->is_active) { + changed = synced_scroll_offset(key)->PushFromMainThread( + new_scroll_offset_map->at(key)->PendingBase()); + + if (new_scroll_offset_map->at(key)->clobber_active_value()) { + synced_scroll_offset(key)->set_clobber_active_value(); + } + if (changed) + layer_tree_impl->LayerById(key)->DidUpdateScrollOffset(); + } else { + layer_id_to_scroll_offset_map_[key] = new_scroll_offset_map->at(key); + changed |= synced_scroll_offset(key)->PushPendingToActive(); + if (changed) + layer_tree_impl->LayerById(key)->DidUpdateScrollOffset(); + } +} + +void ScrollTree::UpdateScrollOffsetMap( + ScrollTree::ScrollOffsetMap* new_scroll_offset_map, + LayerTreeImpl* layer_tree_impl) { + if (layer_tree_impl && layer_tree_impl->root_layer()) { + DCHECK(!property_trees()->is_main_thread); + for (auto map_entry = layer_id_to_scroll_offset_map_.begin(); + map_entry != layer_id_to_scroll_offset_map_.end();) { + int key = map_entry->first; + if (new_scroll_offset_map->find(key) != new_scroll_offset_map->end()) { + UpdateScrollOffsetMapEntry(key, new_scroll_offset_map, layer_tree_impl); + ++map_entry; + } else { + map_entry = layer_id_to_scroll_offset_map_.erase(map_entry); + } + } + + for (auto& map_entry : *new_scroll_offset_map) { + int key = map_entry.first; + if (layer_id_to_scroll_offset_map_.find(key) == + layer_id_to_scroll_offset_map_.end()) + UpdateScrollOffsetMapEntry(key, new_scroll_offset_map, layer_tree_impl); + } + } +} + +ScrollTree::ScrollOffsetMap& ScrollTree::scroll_offset_map() { + return layer_id_to_scroll_offset_map_; +} + +const ScrollTree::ScrollOffsetMap& ScrollTree::scroll_offset_map() const { + return layer_id_to_scroll_offset_map_; +} + +void ScrollTree::ApplySentScrollDeltasFromAbortedCommit() { + DCHECK(property_trees()->is_active); + for (auto& map_entry : layer_id_to_scroll_offset_map_) + map_entry.second->AbortCommit(); +} + +bool ScrollTree::SetScrollOffset(int layer_id, + const gfx::ScrollOffset& scroll_offset) { + if (property_trees()->is_main_thread) + return synced_scroll_offset(layer_id)->PushFromMainThread(scroll_offset); + else if (property_trees()->is_active) + return synced_scroll_offset(layer_id)->SetCurrent(scroll_offset); + return false; +} + PropertyTrees::PropertyTrees() : needs_rebuild(true), non_root_surfaces_enabled(true), changed(false), full_tree_damaged(false), - sequence_number(0) { + sequence_number(0), + is_main_thread(true), + is_active(false) { transform_tree.SetPropertyTrees(this); effect_tree.SetPropertyTrees(this); clip_tree.SetPropertyTrees(this); @@ -1434,6 +1615,8 @@ bool PropertyTrees::operator==(const PropertyTrees& other) const { scroll_tree == other.scroll_tree && needs_rebuild == other.needs_rebuild && changed == other.changed && full_tree_damaged == other.full_tree_damaged && + is_main_thread == other.is_main_thread && + is_active == other.is_active && non_root_surfaces_enabled == other.non_root_surfaces_enabled && sequence_number == other.sequence_number; } @@ -1448,6 +1631,8 @@ PropertyTrees& PropertyTrees::operator=(const PropertyTrees& from) { full_tree_damaged = from.full_tree_damaged; non_root_surfaces_enabled = from.non_root_surfaces_enabled; sequence_number = from.sequence_number; + is_main_thread = from.is_main_thread; + is_active = from.is_active; inner_viewport_container_bounds_delta_ = from.inner_viewport_container_bounds_delta(); outer_viewport_container_bounds_delta_ = @@ -1472,6 +1657,8 @@ void PropertyTrees::ToProtobuf(proto::PropertyTrees* proto) const { proto->set_changed(changed); proto->set_full_tree_damaged(full_tree_damaged); proto->set_non_root_surfaces_enabled(non_root_surfaces_enabled); + proto->set_is_main_thread(is_main_thread); + proto->set_is_active(is_active); // TODO(khushalsagar): Consider using the sequence number to decide if // property trees need to be serialized again for a commit. See crbug/555370. @@ -1490,6 +1677,8 @@ void PropertyTrees::FromProtobuf(const proto::PropertyTrees& proto) { full_tree_damaged = proto.full_tree_damaged(); non_root_surfaces_enabled = proto.non_root_surfaces_enabled(); sequence_number = proto.sequence_number(); + is_main_thread = proto.is_main_thread(); + is_active = proto.is_active(); transform_tree.SetPropertyTrees(this); effect_tree.SetPropertyTrees(this); diff --git a/cc/trees/property_tree.h b/cc/trees/property_tree.h index c35ec8d..c57ad75 100644 --- a/cc/trees/property_tree.h +++ b/cc/trees/property_tree.h @@ -7,9 +7,11 @@ #include <stddef.h> +#include <unordered_map> #include <vector> #include "cc/base/cc_export.h" +#include "cc/base/synced_property.h" #include "ui/gfx/geometry/rect_f.h" #include "ui/gfx/geometry/scroll_offset.h" #include "ui/gfx/transform.h" @@ -27,6 +29,9 @@ class TransformTreeData; class TreeNode; } +class LayerTreeImpl; +struct ScrollAndScaleSet; + // ------------------------------*IMPORTANT*--------------------------------- // Each class declared here has a corresponding proto defined in // cc/proto/property_tree.proto. When making any changes to a class structure @@ -34,6 +39,8 @@ class TreeNode; // change to its proto and the ToProtobuf and FromProtobuf methods for that // class. +typedef SyncedProperty<AdditionGroup<gfx::ScrollOffset>> SyncedScrollOffset; + template <typename T> struct CC_EXPORT TreeNode { TreeNode() : id(-1), parent_id(-1), owner_id(-1), data() {} @@ -551,11 +558,17 @@ class CC_EXPORT ScrollTree final : public PropertyTree<ScrollNode> { ScrollTree(); ~ScrollTree() override; + ScrollTree& operator=(const ScrollTree& from); bool operator==(const ScrollTree& other) const; void ToProtobuf(proto::PropertyTree* proto) const; void FromProtobuf(const proto::PropertyTree& proto); + void clear() override; + + typedef std::unordered_map<int, scoped_refptr<SyncedScrollOffset>> + ScrollOffsetMap; + gfx::ScrollOffset MaxScrollOffset(int scroll_node_id) const; gfx::Size scroll_clip_layer_bounds(int scroll_node_id) const; ScrollNode* CurrentlyScrollingNode(); @@ -563,8 +576,24 @@ class CC_EXPORT ScrollTree final : public PropertyTree<ScrollNode> { void set_currently_scrolling_node(int scroll_node_id); gfx::Transform ScreenSpaceTransform(int scroll_node_id) const; + // synced_scroll_offset is supposed to be called by Layer/LayerImpl only + SyncedScrollOffset* synced_scroll_offset(int layer_id); + void CollectScrollDeltas(ScrollAndScaleSet* scroll_info); + void UpdateScrollOffsetMap(ScrollOffsetMap* new_scroll_offset_map, + LayerTreeImpl* layer_tree_impl); + ScrollOffsetMap& scroll_offset_map(); + const ScrollOffsetMap& scroll_offset_map() const; + void ApplySentScrollDeltasFromAbortedCommit(); + bool SetScrollOffset(int layer_id, const gfx::ScrollOffset& scroll_offset); + private: int currently_scrolling_node_id_; + ScrollOffsetMap layer_id_to_scroll_offset_map_; + + gfx::ScrollOffset PullDeltaForMainThread(SyncedScrollOffset* scroll_offset); + void UpdateScrollOffsetMapEntry(int key, + ScrollOffsetMap* new_scroll_offset_map, + LayerTreeImpl* layer_tree_impl); }; class CC_EXPORT PropertyTrees final { @@ -596,6 +625,8 @@ class CC_EXPORT PropertyTrees final { // individual nodes. bool full_tree_damaged; int sequence_number; + bool is_main_thread; + bool is_active; enum ResetFlags { EFFECT_TREE, TRANSFORM_TREE, ALL_TREES }; void SetInnerViewportContainerBoundsDelta(gfx::Vector2dF bounds_delta); diff --git a/cc/trees/property_tree_builder.cc b/cc/trees/property_tree_builder.cc index 976e076..14338a4 100644 --- a/cc/trees/property_tree_builder.cc +++ b/cc/trees/property_tree_builder.cc @@ -715,6 +715,11 @@ void AddScrollNodeIfNeeded( node.data.main_thread_scrolling_reasons; data_for_children->scroll_tree_parent_created_by_uninheritable_criteria = scroll_node_uninheritable_criteria; + + if (node.data.scrollable) { + data_for_children->scroll_tree->synced_scroll_offset(layer->id()) + ->PushFromMainThread(layer->CurrentScrollOffset()); + } } layer->SetScrollTreeIndex(data_for_children->scroll_tree_parent); @@ -959,6 +964,8 @@ void PropertyTreeBuilder::BuildPropertyTrees( const gfx::Rect& viewport, const gfx::Transform& device_transform, PropertyTrees* property_trees) { + property_trees->is_main_thread = true; + property_trees->is_active = false; SkColor color = root_layer->layer_tree_host()->background_color(); if (SkColorGetA(color) != 255) color = SkColorSetA(color, 255); @@ -981,6 +988,8 @@ void PropertyTreeBuilder::BuildPropertyTrees( const gfx::Rect& viewport, const gfx::Transform& device_transform, PropertyTrees* property_trees) { + property_trees->is_main_thread = false; + property_trees->is_active = root_layer->IsActive(); SkColor color = root_layer->layer_tree_impl()->background_color(); if (SkColorGetA(color) != 255) color = SkColorSetA(color, 255); diff --git a/cc/trees/property_tree_unittest.cc b/cc/trees/property_tree_unittest.cc index cf682a9..0d70672 100644 --- a/cc/trees/property_tree_unittest.cc +++ b/cc/trees/property_tree_unittest.cc @@ -260,7 +260,9 @@ TEST(PropertyTreeSerializationTest, ScrollNodeSerialization) { } TEST(PropertyTreeSerializationTest, ScrollTreeSerialization) { - ScrollTree original; + PropertyTrees property_trees; + property_trees.is_main_thread = true; + ScrollTree& original = property_trees.scroll_tree; ScrollNode second; second.data.scrollable = true; second.data.bounds = gfx::Size(15, 15); @@ -270,6 +272,9 @@ TEST(PropertyTreeSerializationTest, ScrollTreeSerialization) { original.Insert(second, 0); original.Insert(third, 1); + original.set_currently_scrolling_node(1); + original.synced_scroll_offset(1)->PushFromMainThread(gfx::ScrollOffset(1, 2)); + proto::PropertyTree proto; original.ToProtobuf(&proto); ScrollTree result; diff --git a/cc/trees/tree_synchronizer_unittest.cc b/cc/trees/tree_synchronizer_unittest.cc index 95f5f9c..417cda5 100644 --- a/cc/trees/tree_synchronizer_unittest.cc +++ b/cc/trees/tree_synchronizer_unittest.cc @@ -219,6 +219,24 @@ class TreeSynchronizerTest : public testing::Test { TestTaskGraphRunner task_graph_runner_; scoped_ptr<FakeLayerTreeHost> host_; LayerSettings layer_settings_; + + bool is_equal(ScrollTree::ScrollOffsetMap map, + ScrollTree::ScrollOffsetMap other) { + if (map.size() != other.size()) + return false; + for (auto& map_entry : map) { + if (other.find(map_entry.first) == other.end()) + return false; + SyncedScrollOffset& from_map = *map_entry.second.get(); + SyncedScrollOffset& from_other = *other[map_entry.first].get(); + if (from_map.PendingBase() != from_other.PendingBase() || + from_map.ActiveBase() != from_other.ActiveBase() || + from_map.Delta() != from_other.Delta() || + from_map.PendingDelta().get() != from_other.PendingDelta().get()) + return false; + } + return true; + } }; // Attempts to synchronizes a null tree. This should not crash, and should @@ -800,5 +818,102 @@ TEST_F(TreeSynchronizerTest, SynchronizeCurrentlyScrollingNode) { host_impl->active_tree()->CurrentlyScrollingLayer()->id()); } +TEST_F(TreeSynchronizerTest, SynchronizeScrollTreeScrollOffsetMap) { + host_->InitializeSingleThreaded(&client_, base::ThreadTaskRunnerHandle::Get(), + nullptr); + LayerTreeSettings settings; + FakeLayerTreeHostImplClient client; + FakeImplTaskRunnerProvider task_runner_provider; + FakeRenderingStatsInstrumentation stats_instrumentation; + TestSharedBitmapManager shared_bitmap_manager; + TestTaskGraphRunner task_graph_runner; + FakeLayerTreeHostImpl* host_impl = host_->host_impl(); + host_impl->CreatePendingTree(); + + scoped_refptr<Layer> layer_tree_root = Layer::Create(layer_settings_); + scoped_refptr<Layer> scroll_clip_layer = Layer::Create(layer_settings_); + scoped_refptr<Layer> scroll_layer = Layer::Create(layer_settings_); + scoped_refptr<Layer> transient_scroll_clip_layer = + Layer::Create(layer_settings_); + scoped_refptr<Layer> transient_scroll_layer = Layer::Create(layer_settings_); + + layer_tree_root->AddChild(transient_scroll_clip_layer); + transient_scroll_clip_layer->AddChild(transient_scroll_layer); + transient_scroll_layer->AddChild(scroll_clip_layer); + scroll_clip_layer->AddChild(scroll_layer); + + transient_scroll_layer->SetScrollClipLayerId( + transient_scroll_clip_layer->id()); + scroll_layer->SetScrollClipLayerId(scroll_clip_layer->id()); + transient_scroll_layer->SetScrollOffset(gfx::ScrollOffset(1, 2)); + scroll_layer->SetScrollOffset(gfx::ScrollOffset(10, 20)); + + host_->SetRootLayer(layer_tree_root); + host_->BuildPropertyTreesForTesting(); + host_->CommitAndCreatePendingTree(); + host_impl->ActivateSyncTree(); + + ExpectTreesAreIdentical(layer_tree_root.get(), + host_impl->active_tree()->root_layer(), + host_impl->active_tree()); + + // After the initial commit, scroll_offset_map in scroll_tree is expected to + // have one entry for scroll_layer and one entry for transient_scroll_layer, + // the pending base and active base must be the same at this stage. + ScrollTree::ScrollOffsetMap scroll_offset_map; + scroll_offset_map[scroll_layer->id()] = new SyncedScrollOffset; + scroll_offset_map[transient_scroll_layer->id()] = new SyncedScrollOffset; + scroll_offset_map[scroll_layer->id()]->PushFromMainThread( + scroll_layer->scroll_offset()); + scroll_offset_map[scroll_layer->id()]->PushPendingToActive(); + scroll_offset_map[transient_scroll_layer->id()]->PushFromMainThread( + transient_scroll_layer->scroll_offset()); + scroll_offset_map[transient_scroll_layer->id()]->PushPendingToActive(); + EXPECT_TRUE( + is_equal(scroll_offset_map, host_impl->active_tree() + ->property_trees() + ->scroll_tree.scroll_offset_map())); + + // Set ScrollOffset active delta: gfx::ScrollOffset(10, 10) + LayerImpl* scroll_layer_impl = + host_impl->active_tree()->LayerById(scroll_layer->id()); + ScrollTree& scroll_tree = + host_impl->active_tree()->property_trees()->scroll_tree; + scroll_tree.synced_scroll_offset(scroll_layer_impl->id()) + ->SetCurrent(gfx::ScrollOffset(20, 30)); + + // Pull ScrollOffset delta for main thread, and change offset on main thread + scoped_ptr<ScrollAndScaleSet> scroll_info(new ScrollAndScaleSet()); + scroll_tree.CollectScrollDeltas(scroll_info.get()); + host_->proxy()->SetNeedsCommit(); + host_->ApplyScrollAndScale(scroll_info.get()); + EXPECT_EQ(gfx::ScrollOffset(20, 30), scroll_layer->scroll_offset()); + scroll_layer->SetScrollOffset(gfx::ScrollOffset(100, 100)); + + // More update to ScrollOffset active delta: gfx::ScrollOffset(20, 20) + scroll_tree.synced_scroll_offset(scroll_layer_impl->id()) + ->SetCurrent(gfx::ScrollOffset(40, 50)); + host_impl->active_tree()->SetCurrentlyScrollingLayer(scroll_layer_impl); + + // Make one layer unscrollable so that scroll tree topology changes + transient_scroll_layer->SetScrollClipLayerId(Layer::INVALID_ID); + host_->BuildPropertyTreesForTesting(); + + host_impl->CreatePendingTree(); + host_->CommitAndCreatePendingTree(); + host_impl->ActivateSyncTree(); + + EXPECT_EQ(scroll_layer->id(), + host_impl->active_tree()->CurrentlyScrollingLayer()->id()); + scroll_offset_map.erase(transient_scroll_layer->id()); + scroll_offset_map[scroll_layer->id()]->SetCurrent(gfx::ScrollOffset(20, 30)); + scroll_offset_map[scroll_layer->id()]->PullDeltaForMainThread(); + scroll_offset_map[scroll_layer->id()]->SetCurrent(gfx::ScrollOffset(40, 50)); + scroll_offset_map[scroll_layer->id()]->PushFromMainThread( + gfx::ScrollOffset(100, 100)); + scroll_offset_map[scroll_layer->id()]->PushPendingToActive(); + EXPECT_TRUE(is_equal(scroll_offset_map, scroll_tree.scroll_offset_map())); +} + } // namespace } // namespace cc |