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