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/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"
21 class TiledLayerImplTest
: public testing::Test
{
24 : host_impl_(&proxy_
, &shared_bitmap_manager_
, &task_graph_runner_
) {}
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();
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
);
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);
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
);
76 layer
->AppendQuads(render_pass
, &data
);
81 TestSharedBitmapManager shared_bitmap_manager_
;
82 TestTaskGraphRunner task_graph_runner_
;
83 FakeLayerTreeHostImpl host_impl_
;
86 TEST_F(TiledLayerImplTest
, EmptyQuadList
) {
87 gfx::Size
tile_size(90, 90);
90 gfx::Size
layer_size(tile_size
.width() * num_tiles_x
,
91 tile_size
.height() * num_tiles_y
);
93 // Verify default layer does creates quads
95 scoped_ptr
<TiledLayerImpl
> layer
=
96 CreateLayer(tile_size
, layer_size
, LayerTilingData::NO_BORDER_TEXELS
);
97 scoped_ptr
<RenderPass
> render_pass
= RenderPass::Create();
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
);
107 // Layer with empty visible layer rect produces no quads
109 scoped_ptr
<TiledLayerImpl
> layer
=
110 CreateLayer(tile_size
, layer_size
, LayerTilingData::NO_BORDER_TEXELS
);
111 layer
->draw_properties().visible_content_rect
= gfx::Rect();
113 scoped_ptr
<RenderPass
> render_pass
= RenderPass::Create();
115 EXPECT_FALSE(layer
->WillDraw(DRAW_MODE_HARDWARE
, nullptr));
118 // Layer with non-intersecting visible layer rect produces no quads
120 scoped_ptr
<TiledLayerImpl
> layer
=
121 CreateLayer(tile_size
, layer_size
, LayerTilingData::NO_BORDER_TEXELS
);
123 gfx::Rect
outside_bounds(-100, -100, 50, 50);
124 layer
->draw_properties().visible_content_rect
= outside_bounds
;
126 scoped_ptr
<RenderPass
> render_pass
= RenderPass::Create();
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);
135 // Layer with skips draw produces no quads
137 scoped_ptr
<TiledLayerImpl
> layer
=
138 CreateLayer(tile_size
, layer_size
, LayerTilingData::NO_BORDER_TEXELS
);
139 layer
->set_skips_draw(true);
141 scoped_ptr
<RenderPass
> render_pass
= RenderPass::Create();
143 AppendQuadsData data
;
144 layer
->AppendQuads(render_pass
.get(), &data
);
145 EXPECT_EQ(render_pass
->quad_list
.size(), 0u);
149 TEST_F(TiledLayerImplTest
, Checkerboarding
) {
150 gfx::Size
tile_size(10, 10);
153 gfx::Size
layer_size(tile_size
.width() * num_tiles_x
,
154 tile_size
.height() * num_tiles_y
);
156 scoped_ptr
<TiledLayerImpl
> layer
=
157 CreateLayer(tile_size
, layer_size
, LayerTilingData::NO_BORDER_TEXELS
);
159 // No checkerboarding
161 scoped_ptr
<RenderPass
> render_pass
= RenderPass::Create();
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
);
168 for (const auto& quad
: render_pass
->quad_list
)
169 EXPECT_EQ(quad
->material
, DrawQuad::TILED_CONTENT
);
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);
176 // All checkerboarding
178 scoped_ptr
<RenderPass
> render_pass
= RenderPass::Create();
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
);
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); \
194 TEST_F(TiledLayerImplBorderTest, text_fixture_name##HasBorders) { \
195 text_fixture_name(LayerTilingData::HAS_BORDER_TEXELS); \
198 class TiledLayerImplBorderTest
: public TiledLayerImplTest
{
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(),
208 gfx::Rect(layer_size
));
209 LayerTestCommon::VerifyQuadsExactlyCoverRect(render_pass
->quad_list
,
210 gfx::Rect(layer_size
));
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
);
220 gfx::Size
layer_size(250, 250);
221 scoped_ptr
<RenderPass
> render_pass
= RenderPass::Create();
222 GetQuads(render_pass
.get(),
225 LayerTilingData::NO_BORDER_TEXELS
,
226 visible_content_rect
);
227 LayerTestCommon::VerifyQuadsExactlyCoverRect(render_pass
->quad_list
,
228 visible_content_rect
);
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(),
239 LayerTilingData::NO_BORDER_TEXELS
,
240 visible_content_rect
);
241 LayerTestCommon::VerifyQuadsExactlyCoverRect(render_pass
->quad_list
,
242 visible_content_rect
);
245 WITH_AND_WITHOUT_BORDER_TEST(CoverageVisibleRectOnTileBoundaries
);
247 WITH_AND_WITHOUT_BORDER_TEST(CoverageVisibleRectIntersectsTiles
);
249 WITH_AND_WITHOUT_BORDER_TEST(CoverageVisibleRectIntersectsBounds
);
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(),
258 LayerTilingData::NO_BORDER_TEXELS
,
259 gfx::Rect(layer_size
));
261 for (auto iter
= render_pass
->quad_list
.cbegin();
262 iter
!= render_pass
->quad_list
.cend();
264 const TileDrawQuad
* quad
= TileDrawQuad::MaterialCast(*iter
);
266 EXPECT_NE(0u, quad
->resource_id
) << LayerTestCommon::quad_string
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
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
);
282 scoped_ptr
<TiledLayerImpl
> layer
= CreateLayerNoTiles(
283 tile_size
, layer_size
, LayerTilingData::NO_BORDER_TEXELS
);
285 EXPECT_EQ(layer
->GPUMemoryUsageInBytes(), 0u);
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);
293 layer
->GPUMemoryUsageInBytes(),
294 static_cast<size_t>(3 * 4 * tile_size
.width() * tile_size
.height()));
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);
301 EXPECT_EQ(layer
->GPUMemoryUsageInBytes(), 0u);
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
);
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());
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);
323 LayerTestCommon::LayerImplTest impl
;
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);
331 scoped_ptr
<LayerTilingData
> tiler
=
332 LayerTilingData::Create(tile_size
, LayerTilingData::NO_BORDER_TEXELS
);
333 tiler
->SetTilingSize(layer_bounds
);
334 tiled_layer
->SetTilingData(*tiler
);
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);
342 impl
.CalcDrawProps(viewport_size
);
345 SCOPED_TRACE("No occlusion");
347 impl
.AppendQuadsWithOcclusion(tiled_layer
, occluded
);
349 LayerTestCommon::VerifyQuadsExactlyCoverRect(impl
.quad_list(),
350 gfx::Rect(layer_bounds
));
351 EXPECT_EQ(100u, impl
.quad_list().size());
355 SCOPED_TRACE("Full occlusion");
356 gfx::Rect
occluded(tiled_layer
->visible_content_rect());
357 impl
.AppendQuadsWithOcclusion(tiled_layer
, occluded
);
359 LayerTestCommon::VerifyQuadsExactlyCoverRect(impl
.quad_list(), gfx::Rect());
360 EXPECT_EQ(impl
.quad_list().size(), 0u);
364 SCOPED_TRACE("Partial occlusion");
365 gfx::Rect
occluded(150, 0, 200, 1000);
366 impl
.AppendQuadsWithOcclusion(tiled_layer
, occluded
);
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
);