summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cc/layers/picture_layer.cc16
-rw-r--r--cc/layers/picture_layer_impl.cc73
-rw-r--r--cc/layers/picture_layer_impl.h10
-rw-r--r--cc/layers/picture_layer_impl_unittest.cc38
-rw-r--r--cc/test/fake_picture_layer_impl.cc1
-rw-r--r--cc/test/fake_picture_layer_impl.h8
-rw-r--r--cc/trees/layer_tree_host_unittest.cc40
-rw-r--r--cc/trees/layer_tree_host_unittest_scroll.cc108
8 files changed, 215 insertions, 79 deletions
diff --git a/cc/layers/picture_layer.cc b/cc/layers/picture_layer.cc
index 889e2fb..08a5817 100644
--- a/cc/layers/picture_layer.cc
+++ b/cc/layers/picture_layer.cc
@@ -36,25 +36,14 @@ scoped_ptr<LayerImpl> PictureLayer::CreateLayerImpl(LayerTreeImpl* tree_impl) {
void PictureLayer::PushPropertiesTo(LayerImpl* base_layer) {
Layer::PushPropertiesTo(base_layer);
-
PictureLayerImpl* layer_impl = static_cast<PictureLayerImpl*>(base_layer);
- // This should be first so others can use it.
- layer_impl->UpdateTwinLayer();
layer_impl->SetIsMask(is_mask_);
- layer_impl->CreateTilingSetIfNeeded();
// Unlike other properties, invalidation must always be set on layer_impl.
// See PictureLayerImpl::PushPropertiesTo for more details.
layer_impl->invalidation_.Clear();
layer_impl->invalidation_.Swap(&pile_invalidation_);
layer_impl->pile_ = PicturePileImpl::CreateFromOther(pile_.get());
- layer_impl->SyncFromActiveLayer();
-
- // PictureLayer must push properties every frame.
- // TODO(danakj): If we can avoid requiring to do CreateTilingSetIfNeeded() and
- // SyncFromActiveLayer() on every commit then this could go away, maybe
- // conditionally. crbug.com/259402
- needs_push_properties_ = true;
}
void PictureLayer::SetLayerTreeHost(LayerTreeHost* host) {
@@ -114,11 +103,14 @@ bool PictureLayer::Update(ResourceUpdateQueue* queue,
pile_invalidation_,
visible_layer_rect,
rendering_stats_instrumentation());
- if (!updated) {
+ if (updated) {
+ SetNeedsPushProperties();
+ } else {
// If this invalidation did not affect the pile, then it can be cleared as
// an optimization.
pile_invalidation_.Clear();
}
+
return updated;
}
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc
index 4f6052f..5fad7f4 100644
--- a/cc/layers/picture_layer_impl.cc
+++ b/cc/layers/picture_layer_impl.cc
@@ -45,8 +45,8 @@ PictureLayerImpl::PictureLayerImpl(LayerTreeImpl* tree_impl, int id)
raster_contents_scale_(0.f),
low_res_raster_contents_scale_(0.f),
raster_source_scale_was_animating_(false),
- is_using_lcd_text_(tree_impl->settings().can_use_lcd_text) {
-}
+ is_using_lcd_text_(tree_impl->settings().can_use_lcd_text),
+ needs_post_commit_initialization_(true) {}
PictureLayerImpl::~PictureLayerImpl() {
}
@@ -60,13 +60,11 @@ scoped_ptr<LayerImpl> PictureLayerImpl::CreateLayerImpl(
return PictureLayerImpl::Create(tree_impl, id()).PassAs<LayerImpl>();
}
-void PictureLayerImpl::CreateTilingSetIfNeeded() {
- DCHECK(layer_tree_impl()->IsPendingTree());
- if (!tilings_)
- tilings_.reset(new PictureLayerTilingSet(this, bounds()));
-}
-
void PictureLayerImpl::PushPropertiesTo(LayerImpl* base_layer) {
+ // It's possible this layer was never drawn or updated (e.g. because it was
+ // a descendant of an opacity 0 layer).
+ DoPostCommitInitializationIfNeeded();
+
LayerImpl::PushPropertiesTo(base_layer);
PictureLayerImpl* layer_impl = static_cast<PictureLayerImpl*>(base_layer);
@@ -78,8 +76,9 @@ void PictureLayerImpl::PushPropertiesTo(LayerImpl* base_layer) {
layer_impl->SetIsMask(is_mask_);
layer_impl->pile_ = pile_;
- pile_ = NULL;
+ // Tilings would be expensive to push, so we swap. This optimization requires
+ // an extra invalidation in SyncFromActiveLayer.
layer_impl->tilings_.swap(tilings_);
layer_impl->tilings_->SetClient(layer_impl);
if (tilings_)
@@ -92,19 +91,19 @@ void PictureLayerImpl::PushPropertiesTo(LayerImpl* base_layer) {
layer_impl->low_res_raster_contents_scale_ = low_res_raster_contents_scale_;
layer_impl->UpdateLCDTextStatus(is_using_lcd_text_);
+ layer_impl->needs_post_commit_initialization_ = false;
- // As an optimization, don't make a copy of this potentially complex region,
- // and swap it directly from the pending to the active layer. In general, any
- // property pushed to a LayerImpl continues to live on that LayerImpl.
- // However, invalidation is the difference between two main thread frames, so
- // it no longer makes sense once the pending tree gets recycled. It will
- // always get pushed during PictureLayer::PushPropertiesTo.
+ // The invalidation on this soon-to-be-recycled layer must be cleared to
+ // mirror clearing the invalidation in PictureLayer's version of this function
+ // in case push properties is skipped.
layer_impl->invalidation_.Swap(&invalidation_);
invalidation_.Clear();
+ needs_post_commit_initialization_ = true;
}
void PictureLayerImpl::AppendQuads(QuadSink* quad_sink,
AppendQuadsData* append_quads_data) {
+ DCHECK(!needs_post_commit_initialization_);
gfx::Rect rect(visible_content_rect());
gfx::Rect content_rect(content_bounds());
@@ -296,6 +295,7 @@ void PictureLayerImpl::AppendQuads(QuadSink* quad_sink,
}
void PictureLayerImpl::UpdateTilePriorities() {
+ DCHECK(!needs_post_commit_initialization_);
if (!tilings_->num_tilings())
return;
@@ -380,6 +380,7 @@ void PictureLayerImpl::CalculateContentsScale(
float* contents_scale_x,
float* contents_scale_y,
gfx::Size* content_bounds) {
+ DoPostCommitInitializationIfNeeded();
if (!CanHaveTilings()) {
ideal_page_scale_ = page_scale_factor;
ideal_device_scale_ = device_scale_factor;
@@ -525,14 +526,10 @@ gfx::Size PictureLayerImpl::CalculateTileSize(
return default_tile_size;
}
-void PictureLayerImpl::SyncFromActiveLayer() {
- DCHECK(layer_tree_impl()->IsPendingTree());
-
- if (twin_layer_)
- SyncFromActiveLayer(twin_layer_);
-}
-
void PictureLayerImpl::SyncFromActiveLayer(const PictureLayerImpl* other) {
+ DCHECK(!other->needs_post_commit_initialization_);
+ DCHECK(other->tilings_);
+
UpdateLCDTextStatus(other->is_using_lcd_text_);
if (!DrawsContent()) {
@@ -597,15 +594,6 @@ void PictureLayerImpl::SyncTiling(
UpdateTilePriorities();
}
-void PictureLayerImpl::UpdateTwinLayer() {
- DCHECK(layer_tree_impl()->IsPendingTree());
-
- twin_layer_ = static_cast<PictureLayerImpl*>(
- layer_tree_impl()->FindActiveTreeLayerById(id()));
- if (twin_layer_)
- twin_layer_->twin_layer_ = this;
-}
-
void PictureLayerImpl::SetIsMask(bool is_mask) {
if (is_mask_ == is_mask)
return;
@@ -721,6 +709,28 @@ void PictureLayerImpl::MarkVisibleResourcesAsRequired() const {
}
}
+void PictureLayerImpl::DoPostCommitInitialization() {
+ DCHECK(needs_post_commit_initialization_);
+ DCHECK(layer_tree_impl()->IsPendingTree());
+
+ if (!tilings_)
+ tilings_.reset(new PictureLayerTilingSet(this, bounds()));
+
+ DCHECK(!twin_layer_);
+ twin_layer_ = static_cast<PictureLayerImpl*>(
+ layer_tree_impl()->FindActiveTreeLayerById(id()));
+ if (twin_layer_) {
+ DCHECK(!twin_layer_->twin_layer_);
+ twin_layer_->twin_layer_ = this;
+ // If the twin has never been pushed to, do not sync from it.
+ // This can happen if this function is called during activation.
+ if (!twin_layer_->needs_post_commit_initialization_)
+ SyncFromActiveLayer(twin_layer_);
+ }
+
+ needs_post_commit_initialization_ = false;
+}
+
PictureLayerTiling* PictureLayerImpl::AddTiling(float contents_scale) {
DCHECK(CanHaveTilingWithScale(contents_scale)) <<
"contents_scale: " << contents_scale;
@@ -772,6 +782,7 @@ void PictureLayerImpl::ManageTilings(bool animating_transform_to_screen) {
DCHECK(ideal_device_scale_);
DCHECK(ideal_source_scale_);
DCHECK(CanHaveTilings());
+ DCHECK(!needs_post_commit_initialization_);
bool change_target_tiling =
raster_page_scale_ == 0.f ||
diff --git a/cc/layers/picture_layer_impl.h b/cc/layers/picture_layer_impl.h
index 25cc5d0..42efa72 100644
--- a/cc/layers/picture_layer_impl.h
+++ b/cc/layers/picture_layer_impl.h
@@ -62,11 +62,7 @@ class CC_EXPORT PictureLayerImpl
const PictureLayerTiling* tiling) OVERRIDE;
// PushPropertiesTo active tree => pending tree.
- void SyncFromActiveLayer();
void SyncTiling(const PictureLayerTiling* tiling);
- void UpdateTwinLayer();
-
- void CreateTilingSetIfNeeded();
// Mask-related functions
void SetIsMask(bool is_mask);
@@ -92,6 +88,11 @@ class CC_EXPORT PictureLayerImpl
void UpdateLCDTextStatus(bool new_status);
void ResetRasterScale();
void MarkVisibleResourcesAsRequired() const;
+ void DoPostCommitInitializationIfNeeded() {
+ if (needs_post_commit_initialization_)
+ DoPostCommitInitialization();
+ }
+ void DoPostCommitInitialization();
bool CanHaveTilings() const;
bool CanHaveTilingWithScale(float contents_scale) const;
@@ -124,6 +125,7 @@ class CC_EXPORT PictureLayerImpl
bool raster_source_scale_was_animating_;
bool is_using_lcd_text_;
+ bool needs_post_commit_initialization_;
friend class PictureLayer;
DISALLOW_COPY_AND_ASSIGN(PictureLayerImpl);
diff --git a/cc/layers/picture_layer_impl_unittest.cc b/cc/layers/picture_layer_impl_unittest.cc
index b1547ae..56f6d50 100644
--- a/cc/layers/picture_layer_impl_unittest.cc
+++ b/cc/layers/picture_layer_impl_unittest.cc
@@ -70,7 +70,6 @@ class PictureLayerImplTest : public testing::Test {
host_impl_.active_tree()->LayerById(id_));
SetupPendingTree(pending_pile);
- pending_layer_->UpdateTwinLayer();
}
void AddDefaultTilingsWithInvalidation(const Region& invalidation) {
@@ -80,7 +79,6 @@ class PictureLayerImplTest : public testing::Test {
for (size_t i = 0; i < active_layer_->tilings()->num_tilings(); ++i)
active_layer_->tilings()->tiling_at(i)->CreateAllTilesForTesting();
pending_layer_->set_invalidation(invalidation);
- pending_layer_->SyncFromActiveLayer();
for (size_t i = 0; i < pending_layer_->tilings()->num_tilings(); ++i)
pending_layer_->tilings()->tiling_at(i)->CreateAllTilesForTesting();
}
@@ -99,6 +97,7 @@ class PictureLayerImplTest : public testing::Test {
pending_layer_ = static_cast<FakePictureLayerImpl*>(
host_impl_.pending_tree()->LayerById(id_));
+ pending_layer_->DoPostCommitInitializationIfNeeded();
}
static void VerifyAllTilesExistAndHavePile(
@@ -1008,5 +1007,40 @@ TEST_F(PictureLayerImplTest, MarkRequiredOffscreenTiles) {
EXPECT_GT(num_offscreen, 0);
}
+TEST_F(PictureLayerImplTest, ActivateUninitializedLayer) {
+ gfx::Size tile_size(100, 100);
+ gfx::Size layer_bounds(400, 400);
+ scoped_refptr<FakePicturePileImpl> pending_pile =
+ FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+
+ host_impl_.CreatePendingTree();
+ LayerTreeImpl* pending_tree = host_impl_.pending_tree();
+
+ scoped_ptr<FakePictureLayerImpl> pending_layer =
+ FakePictureLayerImpl::CreateWithPile(pending_tree, id_, pending_pile);
+ pending_layer->SetDrawsContent(true);
+ pending_tree->SetRootLayer(pending_layer.PassAs<LayerImpl>());
+
+ pending_layer_ = static_cast<FakePictureLayerImpl*>(
+ host_impl_.pending_tree()->LayerById(id_));
+
+ // Set some state on the pending layer, make sure it is not clobbered
+ // by a sync from the active layer. This could happen because if the
+ // pending layer has not been post-commit initialized it will attempt
+ // to sync from the active layer.
+ bool default_lcd_text_setting = pending_layer_->is_using_lcd_text();
+ pending_layer_->force_set_lcd_text(!default_lcd_text_setting);
+ EXPECT_TRUE(pending_layer_->needs_post_commit_initialization());
+
+ host_impl_.ActivatePendingTree();
+
+ active_layer_ = static_cast<FakePictureLayerImpl*>(
+ host_impl_.active_tree()->LayerById(id_));
+
+ EXPECT_EQ(0u, active_layer_->num_tilings());
+ EXPECT_EQ(!default_lcd_text_setting, active_layer_->is_using_lcd_text());
+ EXPECT_FALSE(active_layer_->needs_post_commit_initialization());
+}
+
} // namespace
} // namespace cc
diff --git a/cc/test/fake_picture_layer_impl.cc b/cc/test/fake_picture_layer_impl.cc
index dd383a6..bdf40a5 100644
--- a/cc/test/fake_picture_layer_impl.cc
+++ b/cc/test/fake_picture_layer_impl.cc
@@ -14,7 +14,6 @@ FakePictureLayerImpl::FakePictureLayerImpl(
append_quads_count_(0) {
pile_ = pile;
SetBounds(pile_->size());
- CreateTilingSetIfNeeded();
}
FakePictureLayerImpl::FakePictureLayerImpl(LayerTreeImpl* tree_impl, int id)
diff --git a/cc/test/fake_picture_layer_impl.h b/cc/test/fake_picture_layer_impl.h
index a0c7829..2eeaeef 100644
--- a/cc/test/fake_picture_layer_impl.h
+++ b/cc/test/fake_picture_layer_impl.h
@@ -32,6 +32,14 @@ class FakePictureLayerImpl : public PictureLayerImpl {
using PictureLayerImpl::CleanUpTilingsOnActiveLayer;
using PictureLayerImpl::CanHaveTilings;
using PictureLayerImpl::MarkVisibleResourcesAsRequired;
+ using PictureLayerImpl::DoPostCommitInitializationIfNeeded;
+
+ bool needs_post_commit_initialization() const {
+ return needs_post_commit_initialization_;
+ }
+
+ bool is_using_lcd_text() const { return is_using_lcd_text_; }
+ void force_set_lcd_text(bool enabled) { is_using_lcd_text_ = enabled; }
PictureLayerTiling* HighResTiling() const;
PictureLayerTiling* LowResTiling() const;
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index d7e7840..07c39a3 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -3506,19 +3506,13 @@ class LayerTreeHostTestLayersPushProperties : public LayerTreeHostTest {
child_ = PushPropertiesCountingLayer::Create();
child2_ = PushPropertiesCountingLayer::Create();
grandchild_ = PushPropertiesCountingLayer::Create();
-
- if (layer_tree_host()->settings().impl_side_painting)
- leaf_picture_layer_ = FakePictureLayer::Create(&client_);
- else
- leaf_content_layer_ = FakeContentLayer::Create(&client_);
+ leaf_scrollbar_layer_ =
+ FakeScrollbarLayer::Create(false, false, root_->id());
root_->AddChild(child_);
root_->AddChild(child2_);
child_->AddChild(grandchild_);
- if (leaf_picture_layer_)
- child2_->AddChild(leaf_picture_layer_);
- if (leaf_content_layer_)
- child2_->AddChild(leaf_content_layer_);
+ child2_->AddChild(leaf_scrollbar_layer_);
other_root_ = PushPropertiesCountingLayer::Create();
@@ -3537,16 +3531,10 @@ class LayerTreeHostTestLayersPushProperties : public LayerTreeHostTest {
child2_->push_properties_count());
EXPECT_EQ(expected_push_properties_other_root_,
other_root_->push_properties_count());
- if (leaf_content_layer_) {
- EXPECT_EQ(expected_push_properties_leaf_layer_,
- leaf_content_layer_->push_properties_count());
- }
- if (leaf_picture_layer_) {
- EXPECT_EQ(expected_push_properties_leaf_layer_,
- leaf_picture_layer_->push_properties_count());
- }
+ EXPECT_EQ(expected_push_properties_leaf_layer_,
+ leaf_scrollbar_layer_->push_properties_count());
- // The content/picture layer always needs to be pushed.
+ // The scrollbar layer always needs to be pushed.
if (root_->layer_tree_host()) {
EXPECT_TRUE(root_->descendant_needs_push_properties());
EXPECT_FALSE(root_->needs_push_properties());
@@ -3555,13 +3543,9 @@ class LayerTreeHostTestLayersPushProperties : public LayerTreeHostTest {
EXPECT_TRUE(child2_->descendant_needs_push_properties());
EXPECT_FALSE(child2_->needs_push_properties());
}
- if (leaf_content_layer_.get() && leaf_content_layer_->layer_tree_host()) {
- EXPECT_FALSE(leaf_content_layer_->descendant_needs_push_properties());
- EXPECT_TRUE(leaf_content_layer_->needs_push_properties());
- }
- if (leaf_picture_layer_.get() && leaf_picture_layer_->layer_tree_host()) {
- EXPECT_FALSE(leaf_picture_layer_->descendant_needs_push_properties());
- EXPECT_TRUE(leaf_picture_layer_->needs_push_properties());
+ if (leaf_scrollbar_layer_->layer_tree_host()) {
+ EXPECT_FALSE(leaf_scrollbar_layer_->descendant_needs_push_properties());
+ EXPECT_TRUE(leaf_scrollbar_layer_->needs_push_properties());
}
// child_ and grandchild_ don't persist their need to push properties.
@@ -3672,8 +3656,7 @@ class LayerTreeHostTestLayersPushProperties : public LayerTreeHostTest {
// Content/Picture layers require PushProperties every commit that they are
// in the tree.
- if ((leaf_content_layer_.get() && leaf_content_layer_->layer_tree_host()) ||
- (leaf_picture_layer_.get() && leaf_picture_layer_->layer_tree_host()))
+ if (leaf_scrollbar_layer_->layer_tree_host())
++expected_push_properties_leaf_layer_;
}
@@ -3686,8 +3669,7 @@ class LayerTreeHostTestLayersPushProperties : public LayerTreeHostTest {
scoped_refptr<PushPropertiesCountingLayer> child2_;
scoped_refptr<PushPropertiesCountingLayer> grandchild_;
scoped_refptr<PushPropertiesCountingLayer> other_root_;
- scoped_refptr<FakeContentLayer> leaf_content_layer_;
- scoped_refptr<FakePictureLayer> leaf_picture_layer_;
+ scoped_refptr<FakeScrollbarLayer> leaf_scrollbar_layer_;
size_t expected_push_properties_root_;
size_t expected_push_properties_child_;
size_t expected_push_properties_child2_;
diff --git a/cc/trees/layer_tree_host_unittest_scroll.cc b/cc/trees/layer_tree_host_unittest_scroll.cc
index 303e924..585d5bf 100644
--- a/cc/trees/layer_tree_host_unittest_scroll.cc
+++ b/cc/trees/layer_tree_host_unittest_scroll.cc
@@ -833,6 +833,114 @@ class ImplSidePaintingScrollTestSimple : public ImplSidePaintingScrollTest {
MULTI_THREAD_TEST_F(ImplSidePaintingScrollTestSimple);
+// This test makes sure that layers pick up scrolls that occur between
+// beginning a commit and finishing a commit (aka scroll deltas not
+// included in sent scroll delta) still apply to layers that don't
+// push properties.
+class ImplSidePaintingScrollTestImplOnlyScroll
+ : public ImplSidePaintingScrollTest {
+ public:
+ ImplSidePaintingScrollTestImplOnlyScroll()
+ : initial_scroll_(20, 10), impl_thread_scroll_(-2, 3) {}
+
+ virtual void BeginTest() OVERRIDE {
+ layer_tree_host()->root_layer()->SetScrollable(true);
+ layer_tree_host()->root_layer()->SetMaxScrollOffset(
+ gfx::Vector2d(100, 100));
+ layer_tree_host()->root_layer()->SetScrollOffset(initial_scroll_);
+ PostSetNeedsCommitToMainThread();
+ }
+
+ virtual void WillCommit() OVERRIDE {
+ Layer* root = layer_tree_host()->root_layer();
+ switch (layer_tree_host()->source_frame_number()) {
+ case 0:
+ EXPECT_TRUE(root->needs_push_properties());
+ break;
+ case 1:
+ // Even if this layer doesn't need push properties, it should
+ // still pick up scrolls that happen on the active layer during
+ // commit.
+ EXPECT_FALSE(root->needs_push_properties());
+ break;
+ }
+ }
+
+ virtual void BeginCommitOnThread(LayerTreeHostImpl* impl) OVERRIDE {
+ // Scroll after the 2nd commit has started.
+ if (impl->active_tree()->source_frame_number() == 0) {
+ LayerImpl* active_root = impl->active_tree()->root_layer();
+ ASSERT_TRUE(active_root);
+ active_root->ScrollBy(impl_thread_scroll_);
+ }
+ }
+
+ virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
+ // We force a second draw here of the first commit before activating
+ // the second commit.
+ LayerImpl* active_root = impl->active_tree()->root_layer();
+ LayerImpl* pending_root = impl->pending_tree()->root_layer();
+
+ ASSERT_TRUE(pending_root);
+ switch (impl->pending_tree()->source_frame_number()) {
+ case 0:
+ EXPECT_VECTOR_EQ(pending_root->scroll_offset(), initial_scroll_);
+ EXPECT_VECTOR_EQ(pending_root->ScrollDelta(), gfx::Vector2d());
+ EXPECT_VECTOR_EQ(pending_root->sent_scroll_delta(), gfx::Vector2d());
+ EXPECT_FALSE(active_root);
+ break;
+ case 1:
+ // Even though the scroll happened during the commit, both layers
+ // should have the appropriate scroll delta.
+ EXPECT_VECTOR_EQ(pending_root->scroll_offset(), initial_scroll_);
+ EXPECT_VECTOR_EQ(pending_root->ScrollDelta(), impl_thread_scroll_);
+ EXPECT_VECTOR_EQ(pending_root->sent_scroll_delta(), gfx::Vector2d());
+ ASSERT_TRUE(active_root);
+ EXPECT_VECTOR_EQ(active_root->scroll_offset(), initial_scroll_);
+ EXPECT_VECTOR_EQ(active_root->ScrollDelta(), impl_thread_scroll_);
+ EXPECT_VECTOR_EQ(active_root->sent_scroll_delta(), gfx::Vector2d());
+ break;
+ case 2:
+ // On the next commit, this delta should have been sent and applied.
+ EXPECT_VECTOR_EQ(pending_root->scroll_offset(),
+ initial_scroll_ + impl_thread_scroll_);
+ EXPECT_VECTOR_EQ(pending_root->ScrollDelta(), gfx::Vector2d());
+ EXPECT_VECTOR_EQ(pending_root->sent_scroll_delta(), gfx::Vector2d());
+ EndTest();
+ break;
+ }
+ }
+
+ virtual void DrawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE {
+ ImplSidePaintingScrollTest::DrawLayersOnThread(impl);
+
+ LayerImpl* root = impl->active_tree()->root_layer();
+
+ switch (impl->active_tree()->source_frame_number()) {
+ case 0:
+ EXPECT_VECTOR_EQ(root->scroll_offset(), initial_scroll_);
+ EXPECT_VECTOR_EQ(root->ScrollDelta(), gfx::Vector2d());
+ EXPECT_VECTOR_EQ(root->sent_scroll_delta(), gfx::Vector2d());
+ PostSetNeedsCommitToMainThread();
+ break;
+ case 1:
+ EXPECT_VECTOR_EQ(root->scroll_offset(), initial_scroll_);
+ EXPECT_VECTOR_EQ(root->ScrollDelta(), impl_thread_scroll_);
+ EXPECT_VECTOR_EQ(root->sent_scroll_delta(), gfx::Vector2d());
+ PostSetNeedsCommitToMainThread();
+ break;
+ }
+ }
+
+ virtual void AfterTest() OVERRIDE {}
+
+ private:
+ gfx::Vector2d initial_scroll_;
+ gfx::Vector2d impl_thread_scroll_;
+};
+
+MULTI_THREAD_TEST_F(ImplSidePaintingScrollTestImplOnlyScroll);
+
class LayerTreeHostScrollTestScrollZeroMaxScrollOffset
: public LayerTreeHostScrollTest {
public: