tiled_layer_impl_unittest.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
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 18namespace cc { 19namespace { 20 21class 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 90TEST_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 161TEST_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 214class 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}; 261WITH_AND_WITHOUT_BORDER_TEST(CoverageVisibleRectOnTileBoundaries); 262 263WITH_AND_WITHOUT_BORDER_TEST(CoverageVisibleRectIntersectsTiles); 264 265WITH_AND_WITHOUT_BORDER_TEST(CoverageVisibleRectIntersectsBounds); 266 267TEST_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 291TEST_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 320TEST_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 331TEST_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