Home | History | Annotate | Download | only in layers
      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/layers/tiled_layer_impl.h"
      6 
      7 #include "cc/layers/append_quads_data.h"
      8 #include "cc/quads/tile_draw_quad.h"
      9 #include "cc/resources/layer_tiling_data.h"
     10 #include "cc/test/fake_impl_proxy.h"
     11 #include "cc/test/fake_layer_tree_host_impl.h"
     12 #include "cc/test/layer_test_common.h"
     13 #include "cc/test/mock_quad_culler.h"
     14 #include "cc/trees/single_thread_proxy.h"
     15 #include "testing/gmock/include/gmock/gmock.h"
     16 #include "testing/gtest/include/gtest/gtest.h"
     17 
     18 namespace cc {
     19 namespace {
     20 
     21 class TiledLayerImplTest : public testing::Test {
     22  public:
     23   TiledLayerImplTest() : host_impl_(&proxy_, &shared_bitmap_manager_) {}
     24 
     25   scoped_ptr<TiledLayerImpl> CreateLayerNoTiles(
     26       const gfx::Size& tile_size,
     27       const gfx::Size& layer_size,
     28       LayerTilingData::BorderTexelOption border_texels) {
     29     scoped_ptr<TiledLayerImpl> layer =
     30         TiledLayerImpl::Create(host_impl_.active_tree(), 1);
     31     scoped_ptr<LayerTilingData> tiler =
     32         LayerTilingData::Create(tile_size, border_texels);
     33     tiler->SetTilingRect(gfx::Rect(layer_size));
     34     layer->SetTilingData(*tiler);
     35     layer->set_skips_draw(false);
     36     layer->draw_properties().visible_content_rect =
     37         gfx::Rect(layer_size);
     38     layer->draw_properties().opacity = 1;
     39     layer->SetBounds(layer_size);
     40     layer->SetContentBounds(layer_size);
     41     layer->CreateRenderSurface();
     42     layer->draw_properties().render_target = layer.get();
     43     return layer.Pass();
     44   }
     45 
     46   // Create a default tiled layer with textures for all tiles and a default
     47   // visibility of the entire layer size.
     48   scoped_ptr<TiledLayerImpl> CreateLayer(
     49       const gfx::Size& tile_size,
     50       const gfx::Size& layer_size,
     51       LayerTilingData::BorderTexelOption border_texels) {
     52     scoped_ptr<TiledLayerImpl> layer =
     53         CreateLayerNoTiles(tile_size, layer_size, border_texels);
     54 
     55     ResourceProvider::ResourceId resource_id = 1;
     56     for (int i = 0; i < layer->TilingForTesting()->num_tiles_x(); ++i) {
     57       for (int j = 0; j < layer->TilingForTesting()->num_tiles_y(); ++j) {
     58         gfx::Rect opaque_rect(
     59             layer->TilingForTesting()->tile_bounds(i, j).origin(),
     60             gfx::Size(1, 1));
     61         layer->PushTileProperties(i, j, resource_id++, opaque_rect, false);
     62       }
     63     }
     64 
     65     return layer.Pass();
     66   }
     67 
     68   void GetQuads(RenderPass* render_pass,
     69                 const gfx::Size& tile_size,
     70                 const gfx::Size& layer_size,
     71                 LayerTilingData::BorderTexelOption border_texel_option,
     72                 const gfx::Rect& visible_content_rect) {
     73     scoped_ptr<TiledLayerImpl> layer =
     74         CreateLayer(tile_size, layer_size, border_texel_option);
     75     layer->draw_properties().visible_content_rect = visible_content_rect;
     76     layer->SetBounds(layer_size);
     77 
     78     MockOcclusionTracker<LayerImpl> occlusion_tracker;
     79     MockQuadCuller quad_culler(render_pass, &occlusion_tracker);
     80     AppendQuadsData data;
     81     layer->AppendQuads(&quad_culler, &data);
     82   }
     83 
     84  protected:
     85   FakeImplProxy proxy_;
     86   TestSharedBitmapManager shared_bitmap_manager_;
     87   FakeLayerTreeHostImpl host_impl_;
     88 };
     89 
     90 TEST_F(TiledLayerImplTest, EmptyQuadList) {
     91   gfx::Size tile_size(90, 90);
     92   int num_tiles_x = 8;
     93   int num_tiles_y = 4;
     94   gfx::Size layer_size(tile_size.width() * num_tiles_x,
     95                        tile_size.height() * num_tiles_y);
     96 
     97   // Verify default layer does creates quads
     98   {
     99     scoped_ptr<TiledLayerImpl> layer =
    100         CreateLayer(tile_size, layer_size, LayerTilingData::NO_BORDER_TEXELS);
    101     MockOcclusionTracker<LayerImpl> occlusion_tracker;
    102     scoped_ptr<RenderPass> render_pass = RenderPass::Create();
    103     MockQuadCuller quad_culler(render_pass.get(), &occlusion_tracker);
    104 
    105     AppendQuadsData data;
    106     EXPECT_TRUE(layer->WillDraw(DRAW_MODE_HARDWARE, NULL));
    107     layer->AppendQuads(&quad_culler, &data);
    108     layer->DidDraw(NULL);
    109     unsigned num_tiles = num_tiles_x * num_tiles_y;
    110     EXPECT_EQ(quad_culler.quad_list().size(), num_tiles);
    111   }
    112 
    113   // Layer with empty visible layer rect produces no quads
    114   {
    115     scoped_ptr<TiledLayerImpl> layer =
    116         CreateLayer(tile_size, layer_size, LayerTilingData::NO_BORDER_TEXELS);
    117     layer->draw_properties().visible_content_rect = gfx::Rect();
    118 
    119     MockOcclusionTracker<LayerImpl> occlusion_tracker;
    120     scoped_ptr<RenderPass> render_pass = RenderPass::Create();
    121     MockQuadCuller quad_culler(render_pass.get(), &occlusion_tracker);
    122 
    123     EXPECT_FALSE(layer->WillDraw(DRAW_MODE_HARDWARE, NULL));
    124   }
    125 
    126   // Layer with non-intersecting visible layer rect produces no quads
    127   {
    128     scoped_ptr<TiledLayerImpl> layer =
    129         CreateLayer(tile_size, layer_size, LayerTilingData::NO_BORDER_TEXELS);
    130 
    131     gfx::Rect outside_bounds(-100, -100, 50, 50);
    132     layer->draw_properties().visible_content_rect = outside_bounds;
    133 
    134     MockOcclusionTracker<LayerImpl> occlusion_tracker;
    135     scoped_ptr<RenderPass> render_pass = RenderPass::Create();
    136     MockQuadCuller quad_culler(render_pass.get(), &occlusion_tracker);
    137 
    138     AppendQuadsData data;
    139     EXPECT_TRUE(layer->WillDraw(DRAW_MODE_HARDWARE, NULL));
    140     layer->AppendQuads(&quad_culler, &data);
    141     layer->DidDraw(NULL);
    142     EXPECT_EQ(quad_culler.quad_list().size(), 0u);
    143   }
    144 
    145   // Layer with skips draw produces no quads
    146   {
    147     scoped_ptr<TiledLayerImpl> layer =
    148         CreateLayer(tile_size, layer_size, LayerTilingData::NO_BORDER_TEXELS);
    149     layer->set_skips_draw(true);
    150 
    151     MockOcclusionTracker<LayerImpl> occlusion_tracker;
    152     scoped_ptr<RenderPass> render_pass = RenderPass::Create();
    153     MockQuadCuller quad_culler(render_pass.get(), &occlusion_tracker);
    154 
    155     AppendQuadsData data;
    156     layer->AppendQuads(&quad_culler, &data);
    157     EXPECT_EQ(quad_culler.quad_list().size(), 0u);
    158   }
    159 }
    160 
    161 TEST_F(TiledLayerImplTest, Checkerboarding) {
    162   gfx::Size tile_size(10, 10);
    163   int num_tiles_x = 2;
    164   int num_tiles_y = 2;
    165   gfx::Size layer_size(tile_size.width() * num_tiles_x,
    166                        tile_size.height() * num_tiles_y);
    167 
    168   scoped_ptr<TiledLayerImpl> layer =
    169       CreateLayer(tile_size, layer_size, LayerTilingData::NO_BORDER_TEXELS);
    170 
    171   // No checkerboarding
    172   {
    173     MockOcclusionTracker<LayerImpl> occlusion_tracker;
    174     scoped_ptr<RenderPass> render_pass = RenderPass::Create();
    175     MockQuadCuller quad_culler(render_pass.get(), &occlusion_tracker);
    176 
    177     AppendQuadsData data;
    178     layer->AppendQuads(&quad_culler, &data);
    179     EXPECT_EQ(quad_culler.quad_list().size(), 4u);
    180     EXPECT_EQ(0u, data.num_missing_tiles);
    181 
    182     for (size_t i = 0; i < quad_culler.quad_list().size(); ++i)
    183       EXPECT_EQ(quad_culler.quad_list()[i]->material, DrawQuad::TILED_CONTENT);
    184   }
    185 
    186   for (int i = 0; i < num_tiles_x; ++i)
    187     for (int j = 0; j < num_tiles_y; ++j)
    188       layer->PushTileProperties(i, j, 0, gfx::Rect(), false);
    189 
    190   // All checkerboarding
    191   {
    192     MockOcclusionTracker<LayerImpl> occlusion_tracker;
    193     scoped_ptr<RenderPass> render_pass = RenderPass::Create();
    194     MockQuadCuller quad_culler(render_pass.get(), &occlusion_tracker);
    195 
    196     AppendQuadsData data;
    197     layer->AppendQuads(&quad_culler, &data);
    198     EXPECT_LT(0u, data.num_missing_tiles);
    199     EXPECT_EQ(quad_culler.quad_list().size(), 4u);
    200     for (size_t i = 0; i < quad_culler.quad_list().size(); ++i)
    201       EXPECT_NE(quad_culler.quad_list()[i]->material, DrawQuad::TILED_CONTENT);
    202   }
    203 }
    204 
    205 // Test with both border texels and without.
    206 #define WITH_AND_WITHOUT_BORDER_TEST(text_fixture_name)                        \
    207   TEST_F(TiledLayerImplBorderTest, text_fixture_name##NoBorders) {             \
    208     text_fixture_name(LayerTilingData::NO_BORDER_TEXELS);                      \
    209   }                                                                            \
    210   TEST_F(TiledLayerImplBorderTest, text_fixture_name##HasBorders) {            \
    211     text_fixture_name(LayerTilingData::HAS_BORDER_TEXELS);                     \
    212   }
    213 
    214 class TiledLayerImplBorderTest : public TiledLayerImplTest {
    215  public:
    216   void CoverageVisibleRectOnTileBoundaries(
    217       LayerTilingData::BorderTexelOption borders) {
    218     gfx::Size layer_size(1000, 1000);
    219     scoped_ptr<RenderPass> render_pass = RenderPass::Create();
    220     GetQuads(render_pass.get(),
    221              gfx::Size(100, 100),
    222              layer_size,
    223              borders,
    224              gfx::Rect(layer_size));
    225     LayerTestCommon::VerifyQuadsExactlyCoverRect(render_pass->quad_list,
    226                                                  gfx::Rect(layer_size));
    227   }
    228 
    229   void CoverageVisibleRectIntersectsTiles(
    230       LayerTilingData::BorderTexelOption borders) {
    231     // This rect intersects the middle 3x3 of the 5x5 tiles.
    232     gfx::Point top_left(65, 73);
    233     gfx::Point bottom_right(182, 198);
    234     gfx::Rect visible_content_rect = gfx::BoundingRect(top_left, bottom_right);
    235 
    236     gfx::Size layer_size(250, 250);
    237     scoped_ptr<RenderPass> render_pass = RenderPass::Create();
    238     GetQuads(render_pass.get(),
    239              gfx::Size(50, 50),
    240              gfx::Size(250, 250),
    241              LayerTilingData::NO_BORDER_TEXELS,
    242              visible_content_rect);
    243     LayerTestCommon::VerifyQuadsExactlyCoverRect(render_pass->quad_list,
    244                                                  visible_content_rect);
    245   }
    246 
    247   void CoverageVisibleRectIntersectsBounds(
    248       LayerTilingData::BorderTexelOption borders) {
    249     gfx::Size layer_size(220, 210);
    250     gfx::Rect visible_content_rect(layer_size);
    251     scoped_ptr<RenderPass> render_pass = RenderPass::Create();
    252     GetQuads(render_pass.get(),
    253              gfx::Size(100, 100),
    254              layer_size,
    255              LayerTilingData::NO_BORDER_TEXELS,
    256              visible_content_rect);
    257     LayerTestCommon::VerifyQuadsExactlyCoverRect(render_pass->quad_list,
    258                                                  visible_content_rect);
    259   }
    260 };
    261 WITH_AND_WITHOUT_BORDER_TEST(CoverageVisibleRectOnTileBoundaries);
    262 
    263 WITH_AND_WITHOUT_BORDER_TEST(CoverageVisibleRectIntersectsTiles);
    264 
    265 WITH_AND_WITHOUT_BORDER_TEST(CoverageVisibleRectIntersectsBounds);
    266 
    267 TEST_F(TiledLayerImplTest, TextureInfoForLayerNoBorders) {
    268   gfx::Size tile_size(50, 50);
    269   gfx::Size layer_size(250, 250);
    270   scoped_ptr<RenderPass> render_pass = RenderPass::Create();
    271   GetQuads(render_pass.get(),
    272            tile_size,
    273            layer_size,
    274            LayerTilingData::NO_BORDER_TEXELS,
    275            gfx::Rect(layer_size));
    276 
    277   for (size_t i = 0; i < render_pass->quad_list.size(); ++i) {
    278     const TileDrawQuad* quad =
    279         TileDrawQuad::MaterialCast(render_pass->quad_list[i]);
    280 
    281     EXPECT_NE(0u, quad->resource_id) << LayerTestCommon::quad_string << i;
    282     EXPECT_EQ(gfx::RectF(gfx::PointF(), tile_size), quad->tex_coord_rect)
    283         << LayerTestCommon::quad_string << i;
    284     EXPECT_EQ(tile_size, quad->texture_size) << LayerTestCommon::quad_string
    285                                              << i;
    286     EXPECT_EQ(gfx::Size(1, 1).ToString(), quad->opaque_rect.size().ToString())
    287         << LayerTestCommon::quad_string << i;
    288   }
    289 }
    290 
    291 TEST_F(TiledLayerImplTest, GPUMemoryUsage) {
    292   gfx::Size tile_size(20, 30);
    293   int num_tiles_x = 12;
    294   int num_tiles_y = 32;
    295   gfx::Size layer_size(tile_size.width() * num_tiles_x,
    296                        tile_size.height() * num_tiles_y);
    297 
    298   scoped_ptr<TiledLayerImpl> layer = CreateLayerNoTiles(
    299       tile_size, layer_size, LayerTilingData::NO_BORDER_TEXELS);
    300 
    301   EXPECT_EQ(layer->GPUMemoryUsageInBytes(), 0u);
    302 
    303   ResourceProvider::ResourceId resource_id = 1;
    304   layer->PushTileProperties(0, 1, resource_id++, gfx::Rect(0, 0, 1, 1), false);
    305   layer->PushTileProperties(2, 3, resource_id++, gfx::Rect(0, 0, 1, 1), false);
    306   layer->PushTileProperties(2, 0, resource_id++, gfx::Rect(0, 0, 1, 1), false);
    307 
    308   EXPECT_EQ(
    309       layer->GPUMemoryUsageInBytes(),
    310       static_cast<size_t>(3 * 4 * tile_size.width() * tile_size.height()));
    311 
    312   ResourceProvider::ResourceId empty_resource(0);
    313   layer->PushTileProperties(0, 1, empty_resource, gfx::Rect(0, 0, 1, 1), false);
    314   layer->PushTileProperties(2, 3, empty_resource, gfx::Rect(0, 0, 1, 1), false);
    315   layer->PushTileProperties(2, 0, empty_resource, gfx::Rect(0, 0, 1, 1), false);
    316 
    317   EXPECT_EQ(layer->GPUMemoryUsageInBytes(), 0u);
    318 }
    319 
    320 TEST_F(TiledLayerImplTest, EmptyMask) {
    321   gfx::Size tile_size(20, 20);
    322   gfx::Size layer_size(0, 0);
    323   scoped_ptr<TiledLayerImpl> layer =
    324       CreateLayer(tile_size, layer_size, LayerTilingData::NO_BORDER_TEXELS);
    325 
    326   EXPECT_EQ(0u, layer->ContentsResourceId());
    327   EXPECT_EQ(0, layer->TilingForTesting()->num_tiles_x());
    328   EXPECT_EQ(0, layer->TilingForTesting()->num_tiles_y());
    329 }
    330 
    331 TEST_F(TiledLayerImplTest, Occlusion) {
    332   gfx::Size tile_size(100, 100);
    333   gfx::Size layer_bounds(1000, 1000);
    334   gfx::Size viewport_size(1000, 1000);
    335 
    336   LayerTestCommon::LayerImplTest impl;
    337 
    338   TiledLayerImpl* tiled_layer = impl.AddChildToRoot<TiledLayerImpl>();
    339   tiled_layer->SetBounds(layer_bounds);
    340   tiled_layer->SetContentBounds(layer_bounds);
    341   tiled_layer->SetDrawsContent(true);
    342   tiled_layer->set_skips_draw(false);
    343 
    344   scoped_ptr<LayerTilingData> tiler =
    345       LayerTilingData::Create(tile_size, LayerTilingData::NO_BORDER_TEXELS);
    346   tiler->SetTilingRect(gfx::Rect(layer_bounds));
    347   tiled_layer->SetTilingData(*tiler);
    348 
    349   ResourceProvider::ResourceId resource_id = 1;
    350   for (int i = 0; i < tiled_layer->TilingForTesting()->num_tiles_x(); ++i) {
    351     for (int j = 0; j < tiled_layer->TilingForTesting()->num_tiles_y(); ++j)
    352       tiled_layer->PushTileProperties(i, j, resource_id++, gfx::Rect(), false);
    353   }
    354 
    355   impl.CalcDrawProps(viewport_size);
    356 
    357   {
    358     SCOPED_TRACE("No occlusion");
    359     gfx::Rect occluded;
    360     impl.AppendQuadsWithOcclusion(tiled_layer, occluded);
    361 
    362     LayerTestCommon::VerifyQuadsExactlyCoverRect(impl.quad_list(),
    363                                                  gfx::Rect(layer_bounds));
    364     EXPECT_EQ(100u, impl.quad_list().size());
    365   }
    366 
    367   {
    368     SCOPED_TRACE("Full occlusion");
    369     gfx::Rect occluded(tiled_layer->visible_content_rect());
    370     impl.AppendQuadsWithOcclusion(tiled_layer, occluded);
    371 
    372     LayerTestCommon::VerifyQuadsExactlyCoverRect(impl.quad_list(), gfx::Rect());
    373     EXPECT_EQ(impl.quad_list().size(), 0u);
    374   }
    375 
    376   {
    377     SCOPED_TRACE("Partial occlusion");
    378     gfx::Rect occluded(150, 0, 200, 1000);
    379     impl.AppendQuadsWithOcclusion(tiled_layer, occluded);
    380 
    381     size_t partially_occluded_count = 0;
    382     LayerTestCommon::VerifyQuadsCoverRectWithOcclusion(
    383         impl.quad_list(),
    384         gfx::Rect(layer_bounds),
    385         occluded,
    386         &partially_occluded_count);
    387     // The layer outputs one quad, which is partially occluded.
    388     EXPECT_EQ(100u - 10u, impl.quad_list().size());
    389     EXPECT_EQ(10u + 10u, partially_occluded_count);
    390   }
    391 }
    392 
    393 }  // namespace
    394 }  // namespace cc
    395