blob: fea056ef111a5f8024dd7dcdade390a2414c687e [file] [log] [blame]
// Copyright 2012 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/trees/layer_tree_host.h"
#include "cc/layers/layer.h"
#include "cc/layers/picture_layer.h"
#include "cc/test/fake_content_layer_client.h"
#include "cc/test/layer_tree_test.h"
#include "cc/trees/layer_tree_impl.h"
namespace cc {
namespace {
#define EXPECT_OCCLUSION_EQ(expected, actual) \
EXPECT_TRUE(expected.IsEqual(actual)) \
<< " Expected: " << expected.ToString() << std::endl \
<< " Actual: " << actual.ToString();
class LayerTreeHostOcclusionTest : public LayerTreeTest {
protected:
void InitializeSettings(LayerTreeSettings* settings) override {
settings->minimum_occlusion_tracking_size = gfx::Size();
}
};
// Verify occlusion is set on the layer draw properties.
class LayerTreeHostOcclusionTestDrawPropertiesOnLayer
: public LayerTreeHostOcclusionTest {
public:
void SetupTree() override {
scoped_refptr<Layer> root = Layer::Create();
root->SetBounds(gfx::Size(100, 100));
root->SetIsDrawable(true);
child_ = Layer::Create();
child_->SetBounds(gfx::Size(50, 60));
child_->SetPosition(gfx::PointF(10.f, 5.5f));
child_->SetContentsOpaque(true);
child_->SetIsDrawable(true);
root->AddChild(child_);
layer_tree_host()->SetRootLayer(root);
LayerTreeTest::SetupTree();
}
void BeginTest() override { PostSetNeedsCommitToMainThread(); }
void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
LayerImpl* root = impl->active_tree()->root_layer_for_testing();
LayerImpl* child = impl->active_tree()->LayerById(child_->id());
// Verify the draw properties are valid.
EXPECT_TRUE(root->is_drawn_render_surface_layer_list_member());
EXPECT_TRUE(child->is_drawn_render_surface_layer_list_member());
EXPECT_OCCLUSION_EQ(
Occlusion(child->DrawTransform(), SimpleEnclosedRegion(),
SimpleEnclosedRegion()),
child->draw_properties().occlusion_in_content_space);
EXPECT_OCCLUSION_EQ(
Occlusion(root->DrawTransform(), SimpleEnclosedRegion(),
SimpleEnclosedRegion(gfx::Rect(10, 6, 50, 59))),
root->draw_properties().occlusion_in_content_space);
EndTest();
}
void AfterTest() override {}
private:
scoped_refptr<Layer> child_;
};
SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostOcclusionTestDrawPropertiesOnLayer);
// Verify occlusion is set on the render surfaces.
class LayerTreeHostOcclusionTestDrawPropertiesOnSurface
: public LayerTreeHostOcclusionTest {
public:
void SetupTree() override {
scoped_refptr<Layer> root = Layer::Create();
root->SetBounds(gfx::Size(100, 100));
root->SetIsDrawable(true);
child_ = Layer::Create();
child_->SetBounds(gfx::Size(1, 1));
child_->SetPosition(gfx::PointF(10.f, 5.5f));
child_->SetIsDrawable(true);
child_->SetForceRenderSurfaceForTesting(true);
root->AddChild(child_);
scoped_refptr<Layer> child2 = Layer::Create();
child2->SetBounds(gfx::Size(10, 12));
child2->SetPosition(gfx::PointF(13.f, 8.5f));
child2->SetContentsOpaque(true);
child2->SetIsDrawable(true);
root->AddChild(child2);
layer_tree_host()->SetRootLayer(root);
LayerTreeTest::SetupTree();
}
void BeginTest() override { PostSetNeedsCommitToMainThread(); }
void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
LayerImpl* root = impl->active_tree()->root_layer_for_testing();
LayerImpl* child = impl->active_tree()->LayerById(child_->id());
RenderSurfaceImpl* surface = child->render_surface();
// Verify the draw properties are valid.
EXPECT_TRUE(root->is_drawn_render_surface_layer_list_member());
EXPECT_TRUE(child->is_drawn_render_surface_layer_list_member());
EXPECT_TRUE(child->has_render_surface());
EXPECT_EQ(child->render_surface(), child->render_target());
EXPECT_OCCLUSION_EQ(
Occlusion(surface->draw_transform(), SimpleEnclosedRegion(),
SimpleEnclosedRegion(gfx::Rect(13, 9, 10, 11))),
surface->occlusion_in_content_space());
EndTest();
}
void AfterTest() override {}
private:
scoped_refptr<Layer> child_;
};
SINGLE_AND_MULTI_THREAD_TEST_F(
LayerTreeHostOcclusionTestDrawPropertiesOnSurface);
// Verify occlusion is set on mask layers.
class LayerTreeHostOcclusionTestDrawPropertiesOnMask
: public LayerTreeHostOcclusionTest {
public:
void SetupTree() override {
scoped_refptr<Layer> root = Layer::Create();
root->SetBounds(gfx::Size(100, 100));
root->SetIsDrawable(true);
child_ = Layer::Create();
child_->SetBounds(gfx::Size(30, 40));
child_->SetPosition(gfx::PointF(10.f, 5.5f));
child_->SetIsDrawable(true);
root->AddChild(child_);
scoped_refptr<Layer> make_surface_bigger = Layer::Create();
make_surface_bigger->SetBounds(gfx::Size(100, 100));
make_surface_bigger->SetPosition(gfx::PointF(-10.f, -15.f));
make_surface_bigger->SetIsDrawable(true);
child_->AddChild(make_surface_bigger);
scoped_refptr<Layer> mask = PictureLayer::Create(&client_);
mask->SetBounds(gfx::Size(30, 40));
mask->SetIsDrawable(true);
child_->SetMaskLayer(mask.get());
scoped_refptr<Layer> child2 = Layer::Create();
child2->SetBounds(gfx::Size(10, 12));
child2->SetPosition(gfx::PointF(13.f, 8.5f));
child2->SetContentsOpaque(true);
child2->SetIsDrawable(true);
root->AddChild(child2);
layer_tree_host()->SetRootLayer(root);
LayerTreeTest::SetupTree();
client_.set_bounds(root->bounds());
}
void BeginTest() override { PostSetNeedsCommitToMainThread(); }
void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
LayerImpl* root = impl->active_tree()->root_layer_for_testing();
LayerImpl* child = impl->active_tree()->LayerById(child_->id());
RenderSurfaceImpl* surface = child->render_surface();
LayerImpl* mask = surface->MaskLayer();
// Verify the draw properties are valid.
EXPECT_TRUE(root->is_drawn_render_surface_layer_list_member());
EXPECT_TRUE(child->is_drawn_render_surface_layer_list_member());
EXPECT_TRUE(child->has_render_surface());
EXPECT_EQ(child->render_surface(), child->render_target());
gfx::Transform transform = surface->draw_transform();
transform.PreconcatTransform(child->DrawTransform());
EXPECT_OCCLUSION_EQ(
Occlusion(transform, SimpleEnclosedRegion(),
SimpleEnclosedRegion(gfx::Rect(13, 9, 10, 11))),
mask->draw_properties().occlusion_in_content_space);
EndTest();
}
void AfterTest() override {}
private:
FakeContentLayerClient client_;
scoped_refptr<Layer> child_;
};
SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostOcclusionTestDrawPropertiesOnMask);
// Verify occlusion is correctly set on scaled mask layers.
class LayerTreeHostOcclusionTestDrawPropertiesOnScaledMask
: public LayerTreeHostOcclusionTest {
public:
void SetupTree() override {
scoped_refptr<Layer> root = Layer::Create();
root->SetBounds(gfx::Size(100, 100));
root->SetIsDrawable(true);
gfx::Transform scale;
scale.Scale(2, 2);
child_ = Layer::Create();
child_->SetBounds(gfx::Size(30, 40));
child_->SetTransform(scale);
root->AddChild(child_);
scoped_refptr<Layer> grand_child = Layer::Create();
grand_child->SetBounds(gfx::Size(100, 100));
grand_child->SetPosition(gfx::PointF(-10.f, -15.f));
grand_child->SetIsDrawable(true);
child_->AddChild(grand_child);
scoped_refptr<Layer> mask = PictureLayer::Create(&client_);
mask->SetBounds(gfx::Size(30, 40));
mask->SetIsDrawable(true);
child_->SetMaskLayer(mask.get());
scoped_refptr<Layer> child2 = Layer::Create();
child2->SetBounds(gfx::Size(10, 11));
child2->SetPosition(gfx::PointF(13.f, 15.f));
child2->SetContentsOpaque(true);
child2->SetIsDrawable(true);
root->AddChild(child2);
layer_tree_host()->SetRootLayer(root);
LayerTreeTest::SetupTree();
client_.set_bounds(root->bounds());
}
void BeginTest() override { PostSetNeedsCommitToMainThread(); }
void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
LayerImpl* child = impl->active_tree()->LayerById(child_->id());
LayerImpl* mask = child->render_surface()->MaskLayer();
gfx::Transform scale;
scale.Scale(2, 2);
EXPECT_OCCLUSION_EQ(
Occlusion(scale, SimpleEnclosedRegion(),
SimpleEnclosedRegion(gfx::Rect(13, 15, 10, 11))),
mask->draw_properties().occlusion_in_content_space);
EndTest();
}
void AfterTest() override {}
private:
FakeContentLayerClient client_;
scoped_refptr<Layer> child_;
};
SINGLE_AND_MULTI_THREAD_TEST_F(
LayerTreeHostOcclusionTestDrawPropertiesOnScaledMask);
// Verify occlusion is set to empty inside the subtree of a replica. This is
// done because the tile system does not know about replicas, and so would not
// know that something is unoccluded on the replica even though it's occluded on
// the original.
class LayerTreeHostOcclusionTestDrawPropertiesInsideReplica
: public LayerTreeHostOcclusionTest {
public:
void SetupTree() override {
scoped_refptr<Layer> root = Layer::Create();
root->SetBounds(gfx::Size(100, 100));
root->SetIsDrawable(true);
child_ = Layer::Create();
child_->SetBounds(gfx::Size(1, 1));
child_->SetPosition(gfx::PointF(10.f, 5.5f));
child_->SetIsDrawable(true);
child_->SetForceRenderSurfaceForTesting(true);
root->AddChild(child_);
scoped_refptr<Layer> replica = Layer::Create();
gfx::Transform translate;
translate.Translate(20.f, 4.f);
replica->SetTransform(translate);
child_->SetReplicaLayer(replica.get());
scoped_refptr<Layer> mask = PictureLayer::Create(&client_);
mask->SetBounds(gfx::Size(30, 40));
mask->SetIsDrawable(true);
child_->SetMaskLayer(mask.get());
scoped_refptr<Layer> child2 = Layer::Create();
child2->SetBounds(gfx::Size(10, 12));
child2->SetPosition(gfx::PointF(13.f, 8.5f));
child2->SetContentsOpaque(true);
child2->SetIsDrawable(true);
root->AddChild(child2);
layer_tree_host()->SetRootLayer(root);
LayerTreeTest::SetupTree();
client_.set_bounds(root->bounds());
}
void BeginTest() override { PostSetNeedsCommitToMainThread(); }
void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
LayerImpl* root = impl->active_tree()->root_layer_for_testing();
LayerImpl* child = impl->active_tree()->LayerById(child_->id());
RenderSurfaceImpl* surface = child->render_surface();
LayerImpl* mask = surface->MaskLayer();
// Verify the draw properties are valid.
EXPECT_TRUE(root->is_drawn_render_surface_layer_list_member());
EXPECT_TRUE(child->is_drawn_render_surface_layer_list_member());
EXPECT_TRUE(child->has_render_surface());
EXPECT_EQ(child->render_surface(), child->render_target());
// No occlusion from on child, which is part of the replica.
EXPECT_OCCLUSION_EQ(Occlusion(),
child->draw_properties().occlusion_in_content_space);
// Occlusion on the surface is okay.
EXPECT_OCCLUSION_EQ(
Occlusion(surface->draw_transform(), SimpleEnclosedRegion(),
SimpleEnclosedRegion(gfx::Rect(13, 9, 10, 11))),
surface->occlusion_in_content_space());
// No occlusion on the replica'd mask.
EXPECT_OCCLUSION_EQ(Occlusion(),
mask->draw_properties().occlusion_in_content_space);
EndTest();
}
void AfterTest() override {}
private:
FakeContentLayerClient client_;
scoped_refptr<Layer> child_;
};
SINGLE_AND_MULTI_THREAD_TEST_F(
LayerTreeHostOcclusionTestDrawPropertiesInsideReplica);
} // namespace
} // namespace cc