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