Home | History | Annotate | Download | only in trees
      1 // Copyright 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "cc/trees/layer_tree_host.h"
      6 
      7 #include "cc/layers/layer.h"
      8 #include "cc/test/layer_tree_test.h"
      9 #include "cc/test/occlusion_tracker_test_common.h"
     10 
     11 namespace cc {
     12 namespace {
     13 
     14 class TestLayer : public Layer {
     15  public:
     16   static scoped_refptr<TestLayer> Create() {
     17     return make_scoped_refptr(new TestLayer());
     18   }
     19 
     20   virtual bool Update(
     21       ResourceUpdateQueue* update_queue,
     22       const OcclusionTracker* occlusion) OVERRIDE {
     23     if (!occlusion)
     24       return false;
     25 
     26     // Gain access to internals of the OcclusionTracker.
     27     const TestOcclusionTracker* test_occlusion =
     28         static_cast<const TestOcclusionTracker*>(occlusion);
     29     occlusion_ = UnionRegions(
     30         test_occlusion->occlusion_from_inside_target(),
     31         test_occlusion->occlusion_from_outside_target());
     32     return false;
     33   }
     34 
     35   const Region& occlusion() const { return occlusion_; }
     36   const Region& expected_occlusion() const { return expected_occlusion_; }
     37   void set_expected_occlusion(const Region& occlusion) {
     38     expected_occlusion_ = occlusion;
     39   }
     40 
     41  private:
     42   TestLayer() : Layer() {
     43     SetIsDrawable(true);
     44   }
     45   virtual ~TestLayer() {}
     46 
     47   Region occlusion_;
     48   Region expected_occlusion_;
     49 };
     50 
     51 class LayerTreeHostOcclusionTest : public LayerTreeTest {
     52  public:
     53   LayerTreeHostOcclusionTest()
     54       : root_(TestLayer::Create()),
     55         child_(TestLayer::Create()),
     56         child2_(TestLayer::Create()),
     57         grand_child_(TestLayer::Create()),
     58         mask_(TestLayer::Create()) {
     59   }
     60 
     61   virtual void BeginTest() OVERRIDE {
     62     PostSetNeedsCommitToMainThread();
     63   }
     64 
     65   virtual void DidCommit() OVERRIDE {
     66     TestLayer* root = static_cast<TestLayer*>(layer_tree_host()->root_layer());
     67     VerifyOcclusion(root);
     68 
     69     EndTest();
     70   }
     71 
     72   virtual void AfterTest() OVERRIDE {}
     73 
     74   void VerifyOcclusion(TestLayer* layer) const {
     75     EXPECT_EQ(layer->expected_occlusion().ToString(),
     76               layer->occlusion().ToString());
     77 
     78     for (size_t i = 0; i < layer->children().size(); ++i) {
     79       TestLayer* child = static_cast<TestLayer*>(layer->children()[i].get());
     80       VerifyOcclusion(child);
     81     }
     82   }
     83 
     84   void SetLayerPropertiesForTesting(TestLayer* layer,
     85                                     TestLayer* parent,
     86                                     const gfx::Transform& transform,
     87                                     gfx::PointF position,
     88                                     gfx::Size bounds,
     89                                     bool opaque) const {
     90     layer->RemoveAllChildren();
     91     if (parent)
     92       parent->AddChild(layer);
     93     layer->SetTransform(transform);
     94     layer->SetPosition(position);
     95     layer->SetBounds(bounds);
     96     layer->SetContentsOpaque(opaque);
     97 
     98     layer->SetAnchorPoint(gfx::PointF());
     99   }
    100 
    101  protected:
    102   scoped_refptr<TestLayer> root_;
    103   scoped_refptr<TestLayer> child_;
    104   scoped_refptr<TestLayer> child2_;
    105   scoped_refptr<TestLayer> grand_child_;
    106   scoped_refptr<TestLayer> mask_;
    107 
    108   gfx::Transform identity_matrix_;
    109 };
    110 
    111 
    112 class LayerTreeHostOcclusionTestOcclusionSurfaceClipping
    113     : public LayerTreeHostOcclusionTest {
    114  public:
    115   virtual void SetupTree() OVERRIDE {
    116     // The child layer is a surface and the grand_child is opaque, but clipped
    117     // to the child and root
    118     SetLayerPropertiesForTesting(
    119         root_.get(), NULL, identity_matrix_,
    120         gfx::PointF(0.f, 0.f), gfx::Size(200, 200), true);
    121     SetLayerPropertiesForTesting(
    122         child_.get(), root_.get(), identity_matrix_,
    123         gfx::PointF(10.f, 10.f), gfx::Size(500, 500), false);
    124     SetLayerPropertiesForTesting(
    125         grand_child_.get(), child_.get(), identity_matrix_,
    126         gfx::PointF(-10.f, -10.f), gfx::Size(20, 500), true);
    127 
    128     child_->SetMasksToBounds(true);
    129     child_->SetForceRenderSurface(true);
    130 
    131     child_->set_expected_occlusion(gfx::Rect(0, 0, 10, 190));
    132     root_->set_expected_occlusion(gfx::Rect(10, 10, 10, 190));
    133 
    134     layer_tree_host()->SetRootLayer(root_);
    135     LayerTreeTest::SetupTree();
    136   }
    137 };
    138 
    139 SINGLE_AND_MULTI_THREAD_TEST_F(
    140     LayerTreeHostOcclusionTestOcclusionSurfaceClipping);
    141 
    142 class LayerTreeHostOcclusionTestOcclusionSurfaceClippingOpaque
    143     : public LayerTreeHostOcclusionTest {
    144  public:
    145   virtual void SetupTree() OVERRIDE {
    146     // If the child layer is opaque, then it adds to the occlusion seen by the
    147     // root_.
    148     SetLayerPropertiesForTesting(
    149         root_.get(), NULL, identity_matrix_,
    150         gfx::PointF(0.f, 0.f), gfx::Size(200, 200), true);
    151     SetLayerPropertiesForTesting(
    152         child_.get(), root_.get(), identity_matrix_,
    153         gfx::PointF(10.f, 10.f), gfx::Size(500, 500), true);
    154     SetLayerPropertiesForTesting(
    155         grand_child_.get(), child_.get(), identity_matrix_,
    156         gfx::PointF(-10.f, -10.f), gfx::Size(20, 500), true);
    157 
    158     child_->SetMasksToBounds(true);
    159     child_->SetForceRenderSurface(true);
    160 
    161     child_->set_expected_occlusion(gfx::Rect(0, 0, 10, 190));
    162     root_->set_expected_occlusion(gfx::Rect(10, 10, 190, 190));
    163 
    164     layer_tree_host()->SetRootLayer(root_);
    165     LayerTreeTest::SetupTree();
    166   }
    167 };
    168 
    169 SINGLE_AND_MULTI_THREAD_TEST_F(
    170     LayerTreeHostOcclusionTestOcclusionSurfaceClippingOpaque);
    171 
    172 class LayerTreeHostOcclusionTestOcclusionTwoChildren
    173     : public LayerTreeHostOcclusionTest {
    174  public:
    175   virtual void SetupTree() OVERRIDE {
    176     // Add a second child to the root layer and the regions should merge
    177     SetLayerPropertiesForTesting(
    178         root_.get(), NULL, identity_matrix_,
    179         gfx::PointF(0.f, 0.f), gfx::Size(200, 200), true);
    180     SetLayerPropertiesForTesting(
    181         child_.get(), root_.get(), identity_matrix_,
    182         gfx::PointF(10.f, 10.f), gfx::Size(500, 500), false);
    183     SetLayerPropertiesForTesting(
    184         grand_child_.get(), child_.get(), identity_matrix_,
    185         gfx::PointF(-10.f, -10.f), gfx::Size(20, 500), true);
    186     SetLayerPropertiesForTesting(
    187         child2_.get(), root_.get(), identity_matrix_,
    188         gfx::PointF(20.f, 10.f), gfx::Size(10, 500), true);
    189 
    190     child_->SetMasksToBounds(true);
    191     child_->SetForceRenderSurface(true);
    192 
    193     grand_child_->set_expected_occlusion(gfx::Rect(10, 0, 10, 190));
    194     child_->set_expected_occlusion(gfx::Rect(0, 0, 20, 190));
    195     root_->set_expected_occlusion(gfx::Rect(10, 10, 20, 190));
    196 
    197     layer_tree_host()->SetRootLayer(root_);
    198     LayerTreeTest::SetupTree();
    199   }
    200 };
    201 
    202 SINGLE_AND_MULTI_THREAD_TEST_F(
    203     LayerTreeHostOcclusionTestOcclusionTwoChildren);
    204 
    205 class LayerTreeHostOcclusionTestOcclusionMask
    206     : public LayerTreeHostOcclusionTest {
    207  public:
    208   virtual void SetupTree() OVERRIDE {
    209     // If the child layer has a mask on it, then it shouldn't contribute to
    210     // occlusion on stuff below it.
    211     SetLayerPropertiesForTesting(
    212         root_.get(), NULL, identity_matrix_,
    213         gfx::PointF(0.f, 0.f), gfx::Size(200, 200), true);
    214     SetLayerPropertiesForTesting(
    215         child2_.get(), root_.get(), identity_matrix_,
    216         gfx::PointF(10.f, 10.f), gfx::Size(500, 500), true);
    217     SetLayerPropertiesForTesting(
    218         child_.get(), root_.get(), identity_matrix_,
    219         gfx::PointF(20.f, 20.f), gfx::Size(500, 500), true);
    220     SetLayerPropertiesForTesting(
    221         grand_child_.get(), child_.get(), identity_matrix_,
    222         gfx::PointF(-10.f, -10.f), gfx::Size(500, 500), true);
    223 
    224     child_->SetMasksToBounds(true);
    225     child_->SetForceRenderSurface(true);
    226     child_->SetMaskLayer(mask_.get());
    227 
    228     child_->set_expected_occlusion(gfx::Rect(0, 0, 180, 180));
    229     root_->set_expected_occlusion(gfx::Rect(10, 10, 190, 190));
    230 
    231     layer_tree_host()->SetRootLayer(root_);
    232     LayerTreeTest::SetupTree();
    233   }
    234 };
    235 
    236 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostOcclusionTestOcclusionMask);
    237 
    238 class LayerTreeHostOcclusionTestOcclusionMaskBelowOcclusion
    239     : public LayerTreeHostOcclusionTest {
    240  public:
    241   virtual void SetupTree() OVERRIDE {
    242     // If the child layer with a mask is below child2, then child2 should
    243     // contribute to occlusion on everything, and child shouldn't contribute
    244     // to the root_.
    245     SetLayerPropertiesForTesting(
    246         root_.get(), NULL, identity_matrix_,
    247         gfx::PointF(0.f, 0.f), gfx::Size(200, 200), true);
    248     SetLayerPropertiesForTesting(
    249         child_.get(), root_.get(), identity_matrix_,
    250         gfx::PointF(10.f, 10.f), gfx::Size(500, 500), true);
    251     SetLayerPropertiesForTesting(
    252         grand_child_.get(), child_.get(), identity_matrix_,
    253         gfx::PointF(-10.f, -10.f), gfx::Size(20, 500), true);
    254     SetLayerPropertiesForTesting(
    255         child2_.get(), root_.get(), identity_matrix_,
    256         gfx::PointF(20.f, 10.f), gfx::Size(10, 500), true);
    257 
    258     child_->SetMasksToBounds(true);
    259     child_->SetForceRenderSurface(true);
    260     child_->SetMaskLayer(mask_.get());
    261 
    262     grand_child_->set_expected_occlusion(gfx::Rect(10, 0, 10, 190));
    263     child_->set_expected_occlusion(gfx::Rect(0, 0, 20, 190));
    264     root_->set_expected_occlusion(gfx::Rect(20, 10, 10, 190));
    265 
    266     layer_tree_host()->SetRootLayer(root_);
    267     LayerTreeTest::SetupTree();
    268   }
    269 };
    270 
    271 SINGLE_AND_MULTI_THREAD_TEST_F(
    272     LayerTreeHostOcclusionTestOcclusionMaskBelowOcclusion);
    273 
    274 class LayerTreeHostOcclusionTestOcclusionOpacity
    275     : public LayerTreeHostOcclusionTest {
    276  public:
    277   virtual void SetupTree() OVERRIDE {
    278     // If the child layer has a non-opaque opacity, then it shouldn't
    279     // contribute to occlusion on stuff below it
    280     SetLayerPropertiesForTesting(
    281         root_.get(), NULL, identity_matrix_,
    282         gfx::PointF(0.f, 0.f), gfx::Size(200, 200), true);
    283     SetLayerPropertiesForTesting(
    284         child2_.get(), root_.get(), identity_matrix_,
    285         gfx::PointF(20.f, 10.f), gfx::Size(10, 500), true);
    286     SetLayerPropertiesForTesting(
    287         child_.get(), root_.get(), identity_matrix_,
    288         gfx::PointF(10.f, 10.f), gfx::Size(500, 500), true);
    289     SetLayerPropertiesForTesting(
    290         grand_child_.get(), child_.get(), identity_matrix_,
    291         gfx::PointF(-10.f, -10.f), gfx::Size(20, 500), true);
    292 
    293     child_->SetMasksToBounds(true);
    294     child_->SetForceRenderSurface(true);
    295     child_->SetOpacity(0.5f);
    296 
    297     child_->set_expected_occlusion(gfx::Rect(0, 0, 10, 190));
    298     root_->set_expected_occlusion(gfx::Rect(20, 10, 10, 190));
    299 
    300     layer_tree_host()->SetRootLayer(root_);
    301     LayerTreeTest::SetupTree();
    302   }
    303 };
    304 
    305 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostOcclusionTestOcclusionOpacity);
    306 
    307 class LayerTreeHostOcclusionTestOcclusionOpacityBelowOcclusion
    308     : public LayerTreeHostOcclusionTest {
    309  public:
    310   virtual void SetupTree() OVERRIDE {
    311     // If the child layer with non-opaque opacity is below child2, then
    312     // child2 should contribute to occlusion on everything, and child shouldn't
    313     // contribute to the root_.
    314     SetLayerPropertiesForTesting(
    315         root_.get(), NULL, identity_matrix_,
    316         gfx::PointF(0.f, 0.f), gfx::Size(200, 200), true);
    317     SetLayerPropertiesForTesting(
    318         child_.get(), root_.get(), identity_matrix_,
    319         gfx::PointF(10.f, 10.f), gfx::Size(500, 500), true);
    320     SetLayerPropertiesForTesting(
    321         grand_child_.get(), child_.get(), identity_matrix_,
    322         gfx::PointF(-10.f, -10.f), gfx::Size(20, 500), true);
    323     SetLayerPropertiesForTesting(
    324         child2_.get(), root_.get(), identity_matrix_,
    325         gfx::PointF(20.f, 10.f), gfx::Size(10, 500), true);
    326 
    327     child_->SetMasksToBounds(true);
    328     child_->SetForceRenderSurface(true);
    329     child_->SetOpacity(0.5f);
    330 
    331     grand_child_->set_expected_occlusion(gfx::Rect(10, 0, 10, 190));
    332     child_->set_expected_occlusion(gfx::Rect(0, 0, 20, 190));
    333     root_->set_expected_occlusion(gfx::Rect(20, 10, 10, 190));
    334 
    335     layer_tree_host()->SetRootLayer(root_);
    336     LayerTreeTest::SetupTree();
    337   }
    338 };
    339 
    340 SINGLE_AND_MULTI_THREAD_TEST_F(
    341     LayerTreeHostOcclusionTestOcclusionOpacityBelowOcclusion);
    342 
    343 class LayerTreeHostOcclusionTestOcclusionOpacityFilter
    344     : public LayerTreeHostOcclusionTest {
    345  public:
    346   virtual void SetupTree() OVERRIDE {
    347     gfx::Transform child_transform;
    348     child_transform.Translate(250.0, 250.0);
    349     child_transform.Rotate(90.0);
    350     child_transform.Translate(-250.0, -250.0);
    351 
    352     FilterOperations filters;
    353     filters.Append(FilterOperation::CreateOpacityFilter(0.5f));
    354 
    355     // If the child layer has a filter that changes alpha values, and is below
    356     // child2, then child2 should contribute to occlusion on everything,
    357     // and child shouldn't contribute to the root
    358     SetLayerPropertiesForTesting(
    359         root_.get(), NULL, identity_matrix_,
    360         gfx::PointF(0.f, 0.f), gfx::Size(200, 200), true);
    361     SetLayerPropertiesForTesting(
    362         child_.get(), root_.get(), child_transform,
    363         gfx::PointF(30.f, 30.f), gfx::Size(500, 500), true);
    364     SetLayerPropertiesForTesting(
    365         grand_child_.get(), child_.get(), identity_matrix_,
    366         gfx::PointF(10.f, 10.f), gfx::Size(500, 500), true);
    367     SetLayerPropertiesForTesting(
    368         child2_.get(), root_.get(), identity_matrix_,
    369         gfx::PointF(10.f, 70.f), gfx::Size(500, 500), true);
    370 
    371     child_->SetMasksToBounds(true);
    372     child_->SetFilters(filters);
    373 
    374     grand_child_->set_expected_occlusion(gfx::Rect(40, 330, 130, 190));
    375     child_->set_expected_occlusion(UnionRegions(
    376         gfx::Rect(10, 330, 160, 170), gfx::Rect(40, 500, 130, 20)));
    377     root_->set_expected_occlusion(gfx::Rect(10, 70, 190, 130));
    378 
    379     layer_tree_host()->SetRootLayer(root_);
    380     LayerTreeTest::SetupTree();
    381   }
    382 };
    383 
    384 SINGLE_AND_MULTI_THREAD_TEST_F(
    385     LayerTreeHostOcclusionTestOcclusionOpacityFilter);
    386 
    387 class LayerTreeHostOcclusionTestOcclusionBlurFilter
    388     : public LayerTreeHostOcclusionTest {
    389  public:
    390   virtual void SetupTree() OVERRIDE {
    391     gfx::Transform child_transform;
    392     child_transform.Translate(250.0, 250.0);
    393     child_transform.Rotate(90.0);
    394     child_transform.Translate(-250.0, -250.0);
    395 
    396     FilterOperations filters;
    397     filters.Append(FilterOperation::CreateBlurFilter(10.f));
    398 
    399     // If the child layer has a filter that moves pixels/changes alpha, and is
    400     // below child2, then child should not inherit occlusion from outside its
    401     // subtree, and should not contribute to the root
    402     SetLayerPropertiesForTesting(
    403         root_.get(), NULL, identity_matrix_,
    404         gfx::PointF(0.f, 0.f), gfx::Size(200, 200), true);
    405     SetLayerPropertiesForTesting(
    406         child_.get(), root_.get(), child_transform,
    407         gfx::PointF(30.f, 30.f), gfx::Size(500, 500), true);
    408     SetLayerPropertiesForTesting(
    409         grand_child_.get(), child_.get(), identity_matrix_,
    410         gfx::PointF(10.f, 10.f), gfx::Size(500, 500), true);
    411     SetLayerPropertiesForTesting(
    412         child2_.get(), root_.get(), identity_matrix_,
    413         gfx::PointF(10.f, 70.f), gfx::Size(500, 500), true);
    414 
    415     child_->SetMasksToBounds(true);
    416     child_->SetFilters(filters);
    417 
    418     child_->set_expected_occlusion(gfx::Rect(10, 330, 160, 170));
    419     root_->set_expected_occlusion(gfx::Rect(10, 70, 190, 130));
    420 
    421     layer_tree_host()->SetRootLayer(root_);
    422     LayerTreeTest::SetupTree();
    423   }
    424 };
    425 
    426 SINGLE_AND_MULTI_THREAD_TEST_F(
    427     LayerTreeHostOcclusionTestOcclusionBlurFilter);
    428 
    429 class LayerTreeHostOcclusionTestManySurfaces
    430     : public LayerTreeHostOcclusionTest {
    431  public:
    432   virtual void SetupTree() OVERRIDE {
    433     // We create enough RenderSurfaces that it will trigger Vector reallocation
    434     // while computing occlusion.
    435     std::vector<scoped_refptr<TestLayer> > layers;
    436     int num_surfaces = 200;
    437     int root_width = 400;
    438     int root_height = 400;
    439 
    440     for (int i = 0; i < num_surfaces; ++i) {
    441       layers.push_back(TestLayer::Create());
    442       if (i == 0) {
    443         SetLayerPropertiesForTesting(
    444             layers.back().get(), NULL, identity_matrix_,
    445             gfx::PointF(0.f, 0.f),
    446             gfx::Size(root_width, root_height), true);
    447       } else {
    448         SetLayerPropertiesForTesting(
    449             layers.back().get(), layers[layers.size() - 2].get(),
    450             identity_matrix_,
    451             gfx::PointF(1.f, 1.f),
    452             gfx::Size(root_width-i, root_height-i), true);
    453         layers.back()->SetForceRenderSurface(true);
    454       }
    455     }
    456 
    457     for (int i = 1; i < num_surfaces; ++i) {
    458       scoped_refptr<TestLayer> child = TestLayer::Create();
    459       SetLayerPropertiesForTesting(
    460           child.get(), layers[i].get(), identity_matrix_,
    461           gfx::PointF(0.f, 0.f), gfx::Size(root_width, root_height), false);
    462     }
    463 
    464     for (int i = 0; i < num_surfaces-1; ++i) {
    465       gfx::Rect expected_occlusion(1, 1, root_width-i-1, root_height-i-1);
    466       layers[i]->set_expected_occlusion(expected_occlusion);
    467     }
    468 
    469     layer_tree_host()->SetRootLayer(layers[0]);
    470     LayerTreeTest::SetupTree();
    471   }
    472 };
    473 
    474 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostOcclusionTestManySurfaces);
    475 
    476 }  // namespace
    477 }  // namespace cc
    478