summaryrefslogtreecommitdiffstats
path: root/cc
diff options
context:
space:
mode:
Diffstat (limited to 'cc')
-rw-r--r--cc/BUILD.gn3
-rw-r--r--cc/base/synced_property.h1
-rw-r--r--cc/cc.gyp3
-rw-r--r--cc/cc_tests.gyp1
-rw-r--r--cc/input/scroll_state.cc3
-rw-r--r--cc/layers/layer.cc19
-rw-r--r--cc/layers/layer_impl.cc101
-rw-r--r--cc/layers/layer_impl.h29
-rw-r--r--cc/layers/layer_impl_unittest.cc13
-rw-r--r--cc/layers/layer_iterator_unittest.cc2
-rw-r--r--cc/layers/picture_image_layer_impl.cc6
-rw-r--r--cc/layers/picture_layer.cc3
-rw-r--r--cc/layers/picture_layer_impl.cc13
-rw-r--r--cc/layers/picture_layer_impl.h16
-rw-r--r--cc/layers/picture_layer_impl_unittest.cc1
-rw-r--r--cc/layers/scrollbar_layer_unittest.cc2
-rw-r--r--cc/proto/BUILD.gn1
-rw-r--r--cc/proto/property_tree.proto11
-rw-r--r--cc/proto/synced_property.proto29
-rw-r--r--cc/proto/synced_property_conversions.cc26
-rw-r--r--cc/proto/synced_property_conversions.h26
-rw-r--r--cc/proto/synced_property_conversions_unittest.cc30
-rw-r--r--cc/test/fake_layer_tree_host.cc2
-rw-r--r--cc/test/fake_picture_layer_impl.cc29
-rw-r--r--cc/test/fake_picture_layer_impl.h5
-rw-r--r--cc/tiles/tile_manager_unittest.cc4
-rw-r--r--cc/trees/layer_tree_host.cc4
-rw-r--r--cc/trees/layer_tree_host_common_unittest.cc9
-rw-r--r--cc/trees/layer_tree_host_impl.cc13
-rw-r--r--cc/trees/layer_tree_host_impl_unittest.cc27
-rw-r--r--cc/trees/layer_tree_impl.cc6
-rw-r--r--cc/trees/layer_tree_impl.h8
-rw-r--r--cc/trees/property_tree.cc197
-rw-r--r--cc/trees/property_tree.h31
-rw-r--r--cc/trees/property_tree_builder.cc9
-rw-r--r--cc/trees/property_tree_unittest.cc7
-rw-r--r--cc/trees/tree_synchronizer_unittest.cc115
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.
diff --git a/cc/cc.gyp b/cc/cc.gyp
index a828910..28453d1 100644
--- a/cc/cc.gyp
+++ b/cc/cc.gyp
@@ -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