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.
5 #include "cc/layers/tiled_layer_impl.h"
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"
20 class TiledLayerImplTest
: public testing::Test
{
22 TiledLayerImplTest() : host_impl_(&proxy_
, &shared_bitmap_manager_
) {}
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
->SetHasRenderSurface(true);
41 layer
->draw_properties().render_target
= layer
.get();
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
);
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);
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
);
74 layer
->AppendQuads(render_pass
, Occlusion(), &data
);
79 TestSharedBitmapManager shared_bitmap_manager_
;
80 FakeLayerTreeHostImpl host_impl_
;
83 TEST_F(TiledLayerImplTest
, EmptyQuadList
) {
84 gfx::Size
tile_size(90, 90);
87 gfx::Size
layer_size(tile_size
.width() * num_tiles_x
,
88 tile_size
.height() * num_tiles_y
);
90 // Verify default layer does creates quads
92 scoped_ptr
<TiledLayerImpl
> layer
=
93 CreateLayer(tile_size
, layer_size
, LayerTilingData::NO_BORDER_TEXELS
);
94 scoped_ptr
<RenderPass
> render_pass
= RenderPass::Create();
97 EXPECT_TRUE(layer
->WillDraw(DRAW_MODE_HARDWARE
, nullptr));
98 layer
->AppendQuads(render_pass
.get(), Occlusion(), &data
);
99 layer
->DidDraw(nullptr);
100 unsigned num_tiles
= num_tiles_x
* num_tiles_y
;
101 EXPECT_EQ(render_pass
->quad_list
.size(), num_tiles
);
104 // Layer with empty visible layer rect produces no quads
106 scoped_ptr
<TiledLayerImpl
> layer
=
107 CreateLayer(tile_size
, layer_size
, LayerTilingData::NO_BORDER_TEXELS
);
108 layer
->draw_properties().visible_content_rect
= gfx::Rect();
110 scoped_ptr
<RenderPass
> render_pass
= RenderPass::Create();
112 EXPECT_FALSE(layer
->WillDraw(DRAW_MODE_HARDWARE
, nullptr));
115 // Layer with non-intersecting visible layer rect produces no quads
117 scoped_ptr
<TiledLayerImpl
> layer
=
118 CreateLayer(tile_size
, layer_size
, LayerTilingData::NO_BORDER_TEXELS
);
120 gfx::Rect
outside_bounds(-100, -100, 50, 50);
121 layer
->draw_properties().visible_content_rect
= outside_bounds
;
123 scoped_ptr
<RenderPass
> render_pass
= RenderPass::Create();
125 AppendQuadsData data
;
126 EXPECT_TRUE(layer
->WillDraw(DRAW_MODE_HARDWARE
, nullptr));
127 layer
->AppendQuads(render_pass
.get(), Occlusion(), &data
);
128 layer
->DidDraw(nullptr);
129 EXPECT_EQ(render_pass
->quad_list
.size(), 0u);
132 // Layer with skips draw produces no quads
134 scoped_ptr
<TiledLayerImpl
> layer
=
135 CreateLayer(tile_size
, layer_size
, LayerTilingData::NO_BORDER_TEXELS
);
136 layer
->set_skips_draw(true);
138 scoped_ptr
<RenderPass
> render_pass
= RenderPass::Create();
140 AppendQuadsData data
;
141 layer
->AppendQuads(render_pass
.get(), Occlusion(), &data
);
142 EXPECT_EQ(render_pass
->quad_list
.size(), 0u);
146 TEST_F(TiledLayerImplTest
, Checkerboarding
) {
147 gfx::Size
tile_size(10, 10);
150 gfx::Size
layer_size(tile_size
.width() * num_tiles_x
,
151 tile_size
.height() * num_tiles_y
);
153 scoped_ptr
<TiledLayerImpl
> layer
=
154 CreateLayer(tile_size
, layer_size
, LayerTilingData::NO_BORDER_TEXELS
);
156 // No checkerboarding
158 scoped_ptr
<RenderPass
> render_pass
= RenderPass::Create();
160 AppendQuadsData data
;
161 layer
->AppendQuads(render_pass
.get(), Occlusion(), &data
);
162 EXPECT_EQ(render_pass
->quad_list
.size(), 4u);
163 EXPECT_EQ(0u, data
.num_missing_tiles
);
165 for (const auto& quad
: render_pass
->quad_list
)
166 EXPECT_EQ(quad
->material
, DrawQuad::TILED_CONTENT
);
169 for (int i
= 0; i
< num_tiles_x
; ++i
)
170 for (int j
= 0; j
< num_tiles_y
; ++j
)
171 layer
->PushTileProperties(i
, j
, 0, false);
173 // All checkerboarding
175 scoped_ptr
<RenderPass
> render_pass
= RenderPass::Create();
177 AppendQuadsData data
;
178 layer
->AppendQuads(render_pass
.get(), Occlusion(), &data
);
179 EXPECT_LT(0u, data
.num_missing_tiles
);
180 EXPECT_EQ(render_pass
->quad_list
.size(), 4u);
181 for (const auto& quad
: render_pass
->quad_list
)
182 EXPECT_NE(quad
->material
, DrawQuad::TILED_CONTENT
);
186 // Test with both border texels and without.
187 #define WITH_AND_WITHOUT_BORDER_TEST(text_fixture_name) \
188 TEST_F(TiledLayerImplBorderTest, text_fixture_name##NoBorders) { \
189 text_fixture_name(LayerTilingData::NO_BORDER_TEXELS); \
191 TEST_F(TiledLayerImplBorderTest, text_fixture_name##HasBorders) { \
192 text_fixture_name(LayerTilingData::HAS_BORDER_TEXELS); \
195 class TiledLayerImplBorderTest
: public TiledLayerImplTest
{
197 void CoverageVisibleRectOnTileBoundaries(
198 LayerTilingData::BorderTexelOption borders
) {
199 gfx::Size
layer_size(1000, 1000);
200 scoped_ptr
<RenderPass
> render_pass
= RenderPass::Create();
201 GetQuads(render_pass
.get(),
205 gfx::Rect(layer_size
));
206 LayerTestCommon::VerifyQuadsExactlyCoverRect(render_pass
->quad_list
,
207 gfx::Rect(layer_size
));
210 void CoverageVisibleRectIntersectsTiles(
211 LayerTilingData::BorderTexelOption borders
) {
212 // This rect intersects the middle 3x3 of the 5x5 tiles.
213 gfx::Point
top_left(65, 73);
214 gfx::Point
bottom_right(182, 198);
215 gfx::Rect visible_content_rect
= gfx::BoundingRect(top_left
, bottom_right
);
217 gfx::Size
layer_size(250, 250);
218 scoped_ptr
<RenderPass
> render_pass
= RenderPass::Create();
219 GetQuads(render_pass
.get(),
222 LayerTilingData::NO_BORDER_TEXELS
,
223 visible_content_rect
);
224 LayerTestCommon::VerifyQuadsExactlyCoverRect(render_pass
->quad_list
,
225 visible_content_rect
);
228 void CoverageVisibleRectIntersectsBounds(
229 LayerTilingData::BorderTexelOption borders
) {
230 gfx::Size
layer_size(220, 210);
231 gfx::Rect
visible_content_rect(layer_size
);
232 scoped_ptr
<RenderPass
> render_pass
= RenderPass::Create();
233 GetQuads(render_pass
.get(),
236 LayerTilingData::NO_BORDER_TEXELS
,
237 visible_content_rect
);
238 LayerTestCommon::VerifyQuadsExactlyCoverRect(render_pass
->quad_list
,
239 visible_content_rect
);
242 WITH_AND_WITHOUT_BORDER_TEST(CoverageVisibleRectOnTileBoundaries
);
244 WITH_AND_WITHOUT_BORDER_TEST(CoverageVisibleRectIntersectsTiles
);
246 WITH_AND_WITHOUT_BORDER_TEST(CoverageVisibleRectIntersectsBounds
);
248 TEST_F(TiledLayerImplTest
, TextureInfoForLayerNoBorders
) {
249 gfx::Size
tile_size(50, 50);
250 gfx::Size
layer_size(250, 250);
251 scoped_ptr
<RenderPass
> render_pass
= RenderPass::Create();
252 GetQuads(render_pass
.get(),
255 LayerTilingData::NO_BORDER_TEXELS
,
256 gfx::Rect(layer_size
));
258 for (auto iter
= render_pass
->quad_list
.cbegin();
259 iter
!= render_pass
->quad_list
.cend();
261 const TileDrawQuad
* quad
= TileDrawQuad::MaterialCast(*iter
);
263 EXPECT_NE(0u, quad
->resource_id
) << LayerTestCommon::quad_string
265 EXPECT_EQ(gfx::RectF(gfx::PointF(), tile_size
), quad
->tex_coord_rect
)
266 << LayerTestCommon::quad_string
<< iter
.index();
267 EXPECT_EQ(tile_size
, quad
->texture_size
) << LayerTestCommon::quad_string
272 TEST_F(TiledLayerImplTest
, GPUMemoryUsage
) {
273 gfx::Size
tile_size(20, 30);
274 int num_tiles_x
= 12;
275 int num_tiles_y
= 32;
276 gfx::Size
layer_size(tile_size
.width() * num_tiles_x
,
277 tile_size
.height() * num_tiles_y
);
279 scoped_ptr
<TiledLayerImpl
> layer
= CreateLayerNoTiles(
280 tile_size
, layer_size
, LayerTilingData::NO_BORDER_TEXELS
);
282 EXPECT_EQ(layer
->GPUMemoryUsageInBytes(), 0u);
284 ResourceProvider::ResourceId resource_id
= 1;
285 layer
->PushTileProperties(0, 1, resource_id
++, false);
286 layer
->PushTileProperties(2, 3, resource_id
++, false);
287 layer
->PushTileProperties(2, 0, resource_id
++, false);
290 layer
->GPUMemoryUsageInBytes(),
291 static_cast<size_t>(3 * 4 * tile_size
.width() * tile_size
.height()));
293 ResourceProvider::ResourceId
empty_resource(0);
294 layer
->PushTileProperties(0, 1, empty_resource
, false);
295 layer
->PushTileProperties(2, 3, empty_resource
, false);
296 layer
->PushTileProperties(2, 0, empty_resource
, false);
298 EXPECT_EQ(layer
->GPUMemoryUsageInBytes(), 0u);
301 TEST_F(TiledLayerImplTest
, EmptyMask
) {
302 gfx::Size
tile_size(20, 20);
303 gfx::Size
layer_size(0, 0);
304 scoped_ptr
<TiledLayerImpl
> layer
=
305 CreateLayer(tile_size
, layer_size
, LayerTilingData::NO_BORDER_TEXELS
);
307 ResourceProvider::ResourceId mask_resource_id
;
308 gfx::Size mask_texture_size
;
309 layer
->GetContentsResourceId(&mask_resource_id
, &mask_texture_size
);
310 EXPECT_EQ(0u, mask_resource_id
);
311 EXPECT_EQ(0, layer
->TilingForTesting()->num_tiles_x());
312 EXPECT_EQ(0, layer
->TilingForTesting()->num_tiles_y());
315 TEST_F(TiledLayerImplTest
, Occlusion
) {
316 gfx::Size
tile_size(100, 100);
317 gfx::Size
layer_bounds(1000, 1000);
318 gfx::Size
viewport_size(1000, 1000);
320 LayerTestCommon::LayerImplTest impl
;
322 TiledLayerImpl
* tiled_layer
= impl
.AddChildToRoot
<TiledLayerImpl
>();
323 tiled_layer
->SetBounds(layer_bounds
);
324 tiled_layer
->SetContentBounds(layer_bounds
);
325 tiled_layer
->SetDrawsContent(true);
326 tiled_layer
->set_skips_draw(false);
328 scoped_ptr
<LayerTilingData
> tiler
=
329 LayerTilingData::Create(tile_size
, LayerTilingData::NO_BORDER_TEXELS
);
330 tiler
->SetTilingSize(layer_bounds
);
331 tiled_layer
->SetTilingData(*tiler
);
333 ResourceProvider::ResourceId resource_id
= 1;
334 for (int i
= 0; i
< tiled_layer
->TilingForTesting()->num_tiles_x(); ++i
) {
335 for (int j
= 0; j
< tiled_layer
->TilingForTesting()->num_tiles_y(); ++j
)
336 tiled_layer
->PushTileProperties(i
, j
, resource_id
++, false);
339 impl
.CalcDrawProps(viewport_size
);
342 SCOPED_TRACE("No occlusion");
344 impl
.AppendQuadsWithOcclusion(tiled_layer
, occluded
);
346 LayerTestCommon::VerifyQuadsExactlyCoverRect(impl
.quad_list(),
347 gfx::Rect(layer_bounds
));
348 EXPECT_EQ(100u, impl
.quad_list().size());
352 SCOPED_TRACE("Full occlusion");
353 gfx::Rect
occluded(tiled_layer
->visible_content_rect());
354 impl
.AppendQuadsWithOcclusion(tiled_layer
, occluded
);
356 LayerTestCommon::VerifyQuadsExactlyCoverRect(impl
.quad_list(), gfx::Rect());
357 EXPECT_EQ(impl
.quad_list().size(), 0u);
361 SCOPED_TRACE("Partial occlusion");
362 gfx::Rect
occluded(150, 0, 200, 1000);
363 impl
.AppendQuadsWithOcclusion(tiled_layer
, occluded
);
365 size_t partially_occluded_count
= 0;
366 LayerTestCommon::VerifyQuadsAreOccluded(
367 impl
.quad_list(), occluded
, &partially_occluded_count
);
368 // The layer outputs one quad, which is partially occluded.
369 EXPECT_EQ(100u - 10u, impl
.quad_list().size());
370 EXPECT_EQ(10u + 10u, partially_occluded_count
);