summaryrefslogtreecommitdiffstats
path: root/cc
diff options
context:
space:
mode:
authorsunxd <sunxd@chromium.org>2016-03-03 14:31:10 -0800
committerCommit bot <commit-bot@chromium.org>2016-03-03 22:32:28 +0000
commitc36713a0336c00a0971fe33514adc01f4df693fa (patch)
tree8e9b76bd9b79b76e1418aecaab20960597fe8c33 /cc
parent1f8acc51c0c5d9fea66917884b927eff8f3e570e (diff)
downloadchromium_src-c36713a0336c00a0971fe33514adc01f4df693fa.zip
chromium_src-c36713a0336c00a0971fe33514adc01f4df693fa.tar.gz
chromium_src-c36713a0336c00a0971fe33514adc01f4df693fa.tar.bz2
cc: Move SyncedScrollOffset to scroll tree
Now updating scrolling information on impl side can be independent of layer impl. There are still some left-over changes corresponding to NoteLayerPropertiesChanged. SyncedScrollOffset of scrollable layers are now stored in property trees instead of layer impl. The main thread property tree has one copy while pending and active share one. BUG=568830 CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel Review URL: https://codereview.chromium.org/1736073002 Cr-Commit-Position: refs/heads/master@{#379116}
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