Commit 72ab277e authored by danakj's avatar danakj Committed by Commit bot

cc: Fix DCHECK when impl thread changes scale on a layer being hidden.

If a layer is being hidden (no longer part of the
RenderSurfaceLayerList), then we will not UpdateTiles to add tilings to
it. If scales change on the active tree, the recycle tree will lose
its tilings, then the hidden layer will have 0 tilings on the pending
tree.

In this case, instead of keeping the non-ideal tilings on the active
tree, and having no high-res tiling, drop the non-ideal tilings from
the active tree.

R=enne, vmpstr
BUG=446751

Review URL: https://codereview.chromium.org/924213002

Cr-Commit-Position: refs/heads/master@{#316368}
parent 233eb509
...@@ -65,6 +65,13 @@ void PictureLayerTilingSet::UpdateTilingsToCurrentRasterSource( ...@@ -65,6 +65,13 @@ void PictureLayerTilingSet::UpdateTilingsToCurrentRasterSource(
// Copy over tilings that are shared with the |twin_set| tiling set (if it // Copy over tilings that are shared with the |twin_set| tiling set (if it
// exists). // exists).
if (twin_set) { if (twin_set) {
if (twin_set->tilings_.empty()) {
// If the twin (pending) tiling set is empty, it was not updated for the
// current frame. So we drop tilings from our set as well, instead of
// leaving behind unshared tilings that are all non-ideal.
RemoveAllTilings();
}
for (PictureLayerTiling* twin_tiling : twin_set->tilings_) { for (PictureLayerTiling* twin_tiling : twin_set->tilings_) {
float contents_scale = twin_tiling->contents_scale(); float contents_scale = twin_tiling->contents_scale();
DCHECK_GE(contents_scale, minimum_contents_scale); DCHECK_GE(contents_scale, minimum_contents_scale);
......
...@@ -327,5 +327,243 @@ class LayerTreeHostPictureTestChangeLiveTilesRectWithRecycleTree ...@@ -327,5 +327,243 @@ class LayerTreeHostPictureTestChangeLiveTilesRectWithRecycleTree
SINGLE_AND_MULTI_THREAD_IMPL_TEST_F( SINGLE_AND_MULTI_THREAD_IMPL_TEST_F(
LayerTreeHostPictureTestChangeLiveTilesRectWithRecycleTree); LayerTreeHostPictureTestChangeLiveTilesRectWithRecycleTree);
class LayerTreeHostPictureTestRSLLMembership : public LayerTreeHostPictureTest {
void SetupTree() override {
scoped_refptr<Layer> root = Layer::Create();
root->SetBounds(gfx::Size(100, 100));
child_ = Layer::Create();
root->AddChild(child_);
// Don't be solid color so the layer has tilings/tiles.
client_.set_fill_with_nonsolid_color(true);
picture_ = FakePictureLayer::Create(&client_);
picture_->SetBounds(gfx::Size(100, 100));
child_->AddChild(picture_);
layer_tree_host()->SetRootLayer(root);
LayerTreeHostPictureTest::SetupTree();
}
void BeginTest() override { PostSetNeedsCommitToMainThread(); }
void WillActivateTreeOnThread(LayerTreeHostImpl* impl) override {
LayerImpl* root = impl->sync_tree()->root_layer();
LayerImpl* child = root->children()[0];
LayerImpl* gchild = child->children()[0];
FakePictureLayerImpl* picture = static_cast<FakePictureLayerImpl*>(gchild);
switch (impl->sync_tree()->source_frame_number()) {
case 0:
// On 1st commit the layer has tilings.
EXPECT_GT(picture->tilings()->num_tilings(), 0u);
break;
case 1:
// On 2nd commit, the layer is transparent, but its tilings are left
// there.
EXPECT_GT(picture->tilings()->num_tilings(), 0u);
break;
case 2:
// On 3rd commit, the layer is visible again, so has tilings.
EXPECT_GT(picture->tilings()->num_tilings(), 0u);
}
}
void DidActivateTreeOnThread(LayerTreeHostImpl* impl) override {
LayerImpl* root = impl->active_tree()->root_layer();
LayerImpl* child = root->children()[0];
LayerImpl* gchild = child->children()[0];
FakePictureLayerImpl* picture = static_cast<FakePictureLayerImpl*>(gchild);
switch (impl->active_tree()->source_frame_number()) {
case 0:
// On 1st commit the layer has tilings.
EXPECT_GT(picture->tilings()->num_tilings(), 0u);
break;
case 1:
// On 2nd commit, the layer is transparent, but its tilings are left
// there.
EXPECT_GT(picture->tilings()->num_tilings(), 0u);
break;
case 2:
// On 3rd commit, the layer is visible again, so has tilings.
EXPECT_GT(picture->tilings()->num_tilings(), 0u);
EndTest();
}
}
void DidCommit() override {
switch (layer_tree_host()->source_frame_number()) {
case 1:
// For the 2nd commit, change opacity to 0 so that the layer will not be
// part of the visible frame.
child_->SetOpacity(0.f);
break;
case 2:
// For the 3rd commit, change opacity to 1 so that the layer will again
// be part of the visible frame.
child_->SetOpacity(1.f);
}
}
void AfterTest() override {}
FakeContentLayerClient client_;
scoped_refptr<Layer> child_;
scoped_refptr<FakePictureLayer> picture_;
};
SINGLE_AND_MULTI_THREAD_IMPL_TEST_F(LayerTreeHostPictureTestRSLLMembership);
class LayerTreeHostPictureTestRSLLMembershipWithScale
: public LayerTreeHostPictureTest {
void SetupTree() override {
scoped_refptr<Layer> root = Layer::Create();
root->SetBounds(gfx::Size(100, 100));
pinch_ = Layer::Create();
pinch_->SetBounds(gfx::Size(500, 500));
pinch_->SetScrollClipLayerId(root->id());
pinch_->SetIsContainerForFixedPositionLayers(true);
root->AddChild(pinch_);
// Don't be solid color so the layer has tilings/tiles.
client_.set_fill_with_nonsolid_color(true);
picture_ = FakePictureLayer::Create(&client_);
picture_->SetBounds(gfx::Size(100, 100));
pinch_->AddChild(picture_);
layer_tree_host()->RegisterViewportLayers(NULL, root, pinch_, pinch_);
layer_tree_host()->SetPageScaleFactorAndLimits(1.f, 1.f, 4.f);
layer_tree_host()->SetRootLayer(root);
LayerTreeHostPictureTest::SetupTree();
}
void InitializeSettings(LayerTreeSettings* settings) override {
settings->layer_transforms_should_scale_layer_contents = true;
}
void BeginTest() override {
frame_ = 0;
draws_in_frame_ = 0;
last_frame_drawn_ = -1;
PostSetNeedsCommitToMainThread();
}
void WillActivateTreeOnThread(LayerTreeHostImpl* impl) override {
LayerImpl* root = impl->sync_tree()->root_layer();
LayerImpl* pinch = root->children()[0];
LayerImpl* gchild = pinch->children()[0];
FakePictureLayerImpl* picture = static_cast<FakePictureLayerImpl*>(gchild);
switch (frame_) {
case 0:
// On 1st commit the layer has tilings.
EXPECT_GT(picture->tilings()->num_tilings(), 0u);
break;
case 1:
// On 2nd commit, the layer is transparent, so does not have tilings.
EXPECT_EQ(0u, picture->tilings()->num_tilings());
break;
case 2:
// On 3rd commit, the layer is visible again, so has tilings.
EXPECT_GT(picture->tilings()->num_tilings(), 0u);
}
}
void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
LayerImpl* root = impl->active_tree()->root_layer();
LayerImpl* pinch = root->children()[0];
LayerImpl* gchild = pinch->children()[0];
FakePictureLayerImpl* picture = static_cast<FakePictureLayerImpl*>(gchild);
if (frame_ != last_frame_drawn_)
draws_in_frame_ = 0;
++draws_in_frame_;
last_frame_drawn_ = frame_;
switch (frame_) {
case 0:
if (draws_in_frame_ == 1) {
// On 1st commit the layer has tilings.
EXPECT_GT(picture->tilings()->num_tilings(), 0u);
EXPECT_EQ(1.f, picture->HighResTiling()->contents_scale());
// Pinch zoom in to change the scale on the active tree.
impl->PinchGestureBegin();
impl->PinchGestureUpdate(2.f, gfx::Point(1, 1));
impl->PinchGestureEnd();
} else if (picture->tilings()->num_tilings() == 1) {
// If the pinch gesture caused a commit we could get here with a
// pending tree.
EXPECT_FALSE(impl->pending_tree());
// The active layer now has only a 2.f scale tiling, which means the
// recycled layer's tiling is destroyed.
EXPECT_EQ(2.f, picture->HighResTiling()->contents_scale());
EXPECT_EQ(0u, picture->GetRecycledTwinLayer()
->picture_layer_tiling_set()
->num_tilings());
++frame_;
MainThreadTaskRunner()->PostTask(
FROM_HERE,
base::Bind(
&LayerTreeHostPictureTestRSLLMembershipWithScale::NextStep,
base::Unretained(this)));
}
break;
case 1:
EXPECT_EQ(1, draws_in_frame_);
// On 2nd commit, the layer is transparent, so does not create
// tilings. Since the 1.f tiling was destroyed in the recycle tree, it
// has no tilings left. This is propogated to the active tree.
EXPECT_EQ(0u, picture->picture_layer_tiling_set()->num_tilings());
EXPECT_EQ(0u, picture->GetRecycledTwinLayer()
->picture_layer_tiling_set()
->num_tilings());
++frame_;
MainThreadTaskRunner()->PostTask(
FROM_HERE,
base::Bind(
&LayerTreeHostPictureTestRSLLMembershipWithScale::NextStep,
base::Unretained(this)));
break;
case 2:
EXPECT_EQ(1, draws_in_frame_);
// On 3rd commit, the layer is visible again, so has tilings.
EXPECT_GT(picture->tilings()->num_tilings(), 0u);
EndTest();
}
}
void NextStep() {
switch (frame_) {
case 1:
// For the 2nd commit, change opacity to 0 so that the layer will not be
// part of the visible frame.
pinch_->SetOpacity(0.f);
break;
case 2:
// For the 3rd commit, change opacity to 1 so that the layer will again
// be part of the visible frame.
pinch_->SetOpacity(1.f);
break;
}
}
void AfterTest() override {}
FakeContentLayerClient client_;
scoped_refptr<Layer> pinch_;
scoped_refptr<FakePictureLayer> picture_;
int frame_;
int draws_in_frame_;
int last_frame_drawn_;
};
// Multi-thread only because in single thread you can't pinch zoom on the
// compositor thread.
MULTI_THREAD_IMPL_TEST_F(LayerTreeHostPictureTestRSLLMembershipWithScale);
} // namespace } // namespace
} // namespace cc } // namespace cc
...@@ -657,7 +657,6 @@ bool LayerTreeImpl::UpdateDrawProperties() { ...@@ -657,7 +657,6 @@ bool LayerTreeImpl::UpdateDrawProperties() {
size_t layers_updated_count = 0; size_t layers_updated_count = 0;
bool tile_priorities_updated = false; bool tile_priorities_updated = false;
for (PictureLayerImpl* layer : picture_layers_) { for (PictureLayerImpl* layer : picture_layers_) {
// TODO(danakj): Remove this to fix crbug.com/446751
if (!layer->IsDrawnRenderSurfaceLayerListMember()) if (!layer->IsDrawnRenderSurfaceLayerListMember())
continue; continue;
++layers_updated_count; ++layers_updated_count;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment