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/fake_output_surface.h"
13 #include "cc/test/layer_test_common.h"
14 #include "cc/test/test_task_graph_runner.h"
15 #include "cc/trees/single_thread_proxy.h"
16 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h"
22 class TiledLayerImplTest
: public testing::Test
{
25 : host_impl_(&proxy_
, &shared_bitmap_manager_
, &task_graph_runner_
) {
26 host_impl_
.InitializeRenderer(FakeOutputSurface::Create3d());
29 scoped_ptr
<TiledLayerImpl
> CreateLayerNoTiles(
30 const gfx::Size
& tile_size
,
31 const gfx::Size
& layer_size
,
32 LayerTilingData::BorderTexelOption border_texels
) {
33 scoped_ptr
<TiledLayerImpl
> layer
=
34 TiledLayerImpl::Create(host_impl_
.active_tree(), 1);
35 scoped_ptr
<LayerTilingData
> tiler
=
36 LayerTilingData::Create(tile_size
, border_texels
);
37 tiler
->SetTilingSize(layer_size
);
38 layer
->SetTilingData(*tiler
);
39 layer
->set_skips_draw(false);
40 layer
->draw_properties().visible_content_rect
=
41 gfx::Rect(layer_size
);
42 layer
->draw_properties().opacity
= 1;
43 layer
->SetBounds(layer_size
);
44 layer
->SetContentBounds(layer_size
);
45 layer
->SetHasRenderSurface(true);
46 layer
->draw_properties().render_target
= layer
.get();
50 // Create a default tiled layer with textures for all tiles and a default
51 // visibility of the entire layer size.
52 scoped_ptr
<TiledLayerImpl
> CreateLayer(
53 const gfx::Size
& tile_size
,
54 const gfx::Size
& layer_size
,
55 LayerTilingData::BorderTexelOption border_texels
) {
56 scoped_ptr
<TiledLayerImpl
> layer
=
57 CreateLayerNoTiles(tile_size
, layer_size
, border_texels
);
59 for (int i
= 0; i
< layer
->TilingForTesting()->num_tiles_x(); ++i
) {
60 for (int j
= 0; j
< layer
->TilingForTesting()->num_tiles_y(); ++j
) {
61 ResourceProvider::ResourceId resource_id
=
62 host_impl_
.resource_provider()->CreateResource(
63 gfx::Size(1, 1), GL_CLAMP_TO_EDGE
,
64 ResourceProvider::TEXTURE_HINT_IMMUTABLE
, RGBA_8888
);
65 layer
->PushTileProperties(i
, j
, resource_id
, false);
72 void GetQuads(RenderPass
* render_pass
,
73 const gfx::Size
& tile_size
,
74 const gfx::Size
& layer_size
,
75 LayerTilingData::BorderTexelOption border_texel_option
,
76 const gfx::Rect
& visible_content_rect
) {
77 scoped_ptr
<TiledLayerImpl
> layer
=
78 CreateLayer(tile_size
, layer_size
, border_texel_option
);
79 layer
->draw_properties().visible_content_rect
= visible_content_rect
;
80 layer
->SetBounds(layer_size
);
83 layer
->AppendQuads(render_pass
, &data
);
88 TestSharedBitmapManager shared_bitmap_manager_
;
89 TestTaskGraphRunner task_graph_runner_
;
90 FakeLayerTreeHostImpl host_impl_
;
93 TEST_F(TiledLayerImplTest
, EmptyQuadList
) {
94 gfx::Size
tile_size(90, 90);
97 gfx::Size
layer_size(tile_size
.width() * num_tiles_x
,
98 tile_size
.height() * num_tiles_y
);
100 // Verify default layer does creates quads
102 scoped_ptr
<TiledLayerImpl
> layer
=
103 CreateLayer(tile_size
, layer_size
, LayerTilingData::NO_BORDER_TEXELS
);
104 scoped_ptr
<RenderPass
> render_pass
= RenderPass::Create();
106 AppendQuadsData data
;
107 EXPECT_TRUE(layer
->WillDraw(DRAW_MODE_HARDWARE
, nullptr));
108 layer
->AppendQuads(render_pass
.get(), &data
);
109 layer
->DidDraw(nullptr);
110 unsigned num_tiles
= num_tiles_x
* num_tiles_y
;
111 EXPECT_EQ(render_pass
->quad_list
.size(), num_tiles
);
114 // Layer with empty visible layer rect produces no quads
116 scoped_ptr
<TiledLayerImpl
> layer
=
117 CreateLayer(tile_size
, layer_size
, LayerTilingData::NO_BORDER_TEXELS
);
118 layer
->draw_properties().visible_content_rect
= gfx::Rect();
120 scoped_ptr
<RenderPass
> render_pass
= RenderPass::Create();
122 EXPECT_FALSE(layer
->WillDraw(DRAW_MODE_HARDWARE
, nullptr));
125 // Layer with non-intersecting visible layer rect produces no quads
127 scoped_ptr
<TiledLayerImpl
> layer
=
128 CreateLayer(tile_size
, layer_size
, LayerTilingData::NO_BORDER_TEXELS
);
130 gfx::Rect
outside_bounds(-100, -100, 50, 50);
131 layer
->draw_properties().visible_content_rect
= outside_bounds
;
133 scoped_ptr
<RenderPass
> render_pass
= RenderPass::Create();
135 AppendQuadsData data
;
136 EXPECT_TRUE(layer
->WillDraw(DRAW_MODE_HARDWARE
, nullptr));
137 layer
->AppendQuads(render_pass
.get(), &data
);
138 layer
->DidDraw(nullptr);
139 EXPECT_EQ(render_pass
->quad_list
.size(), 0u);
142 // Layer with skips draw produces no quads
144 scoped_ptr
<TiledLayerImpl
> layer
=
145 CreateLayer(tile_size
, layer_size
, LayerTilingData::NO_BORDER_TEXELS
);
146 layer
->set_skips_draw(true);
148 scoped_ptr
<RenderPass
> render_pass
= RenderPass::Create();
150 AppendQuadsData data
;
151 layer
->AppendQuads(render_pass
.get(), &data
);
152 EXPECT_EQ(render_pass
->quad_list
.size(), 0u);
156 TEST_F(TiledLayerImplTest
, Checkerboarding
) {
157 gfx::Size
tile_size(10, 10);
160 gfx::Size
layer_size(tile_size
.width() * num_tiles_x
,
161 tile_size
.height() * num_tiles_y
);
163 scoped_ptr
<TiledLayerImpl
> layer
=
164 CreateLayer(tile_size
, layer_size
, LayerTilingData::NO_BORDER_TEXELS
);
166 // No checkerboarding
168 scoped_ptr
<RenderPass
> render_pass
= RenderPass::Create();
170 AppendQuadsData data
;
171 layer
->AppendQuads(render_pass
.get(), &data
);
172 EXPECT_EQ(render_pass
->quad_list
.size(), 4u);
173 EXPECT_EQ(0u, data
.num_missing_tiles
);
175 for (const auto& quad
: render_pass
->quad_list
)
176 EXPECT_EQ(quad
->material
, DrawQuad::TILED_CONTENT
);
179 for (int i
= 0; i
< num_tiles_x
; ++i
)
180 for (int j
= 0; j
< num_tiles_y
; ++j
)
181 layer
->PushTileProperties(i
, j
, 0, false);
183 // All checkerboarding
185 scoped_ptr
<RenderPass
> render_pass
= RenderPass::Create();
187 AppendQuadsData data
;
188 layer
->AppendQuads(render_pass
.get(), &data
);
189 EXPECT_LT(0u, data
.num_missing_tiles
);
190 EXPECT_EQ(render_pass
->quad_list
.size(), 4u);
191 for (const auto& quad
: render_pass
->quad_list
)
192 EXPECT_NE(quad
->material
, DrawQuad::TILED_CONTENT
);
196 // Test with both border texels and without.
197 #define WITH_AND_WITHOUT_BORDER_TEST(text_fixture_name) \
198 TEST_F(TiledLayerImplBorderTest, text_fixture_name##NoBorders) { \
199 text_fixture_name(LayerTilingData::NO_BORDER_TEXELS); \
201 TEST_F(TiledLayerImplBorderTest, text_fixture_name##HasBorders) { \
202 text_fixture_name(LayerTilingData::HAS_BORDER_TEXELS); \
205 class TiledLayerImplBorderTest
: public TiledLayerImplTest
{
207 void CoverageVisibleRectOnTileBoundaries(
208 LayerTilingData::BorderTexelOption borders
) {
209 gfx::Size
layer_size(1000, 1000);
210 scoped_ptr
<RenderPass
> render_pass
= RenderPass::Create();
211 GetQuads(render_pass
.get(),
215 gfx::Rect(layer_size
));
216 LayerTestCommon::VerifyQuadsExactlyCoverRect(render_pass
->quad_list
,
217 gfx::Rect(layer_size
));
220 void CoverageVisibleRectIntersectsTiles(
221 LayerTilingData::BorderTexelOption borders
) {
222 // This rect intersects the middle 3x3 of the 5x5 tiles.
223 gfx::Point
top_left(65, 73);
224 gfx::Point
bottom_right(182, 198);
225 gfx::Rect visible_content_rect
= gfx::BoundingRect(top_left
, bottom_right
);
227 gfx::Size
layer_size(250, 250);
228 scoped_ptr
<RenderPass
> render_pass
= RenderPass::Create();
229 GetQuads(render_pass
.get(),
232 LayerTilingData::NO_BORDER_TEXELS
,
233 visible_content_rect
);
234 LayerTestCommon::VerifyQuadsExactlyCoverRect(render_pass
->quad_list
,
235 visible_content_rect
);
238 void CoverageVisibleRectIntersectsBounds(
239 LayerTilingData::BorderTexelOption borders
) {
240 gfx::Size
layer_size(220, 210);
241 gfx::Rect
visible_content_rect(layer_size
);
242 scoped_ptr
<RenderPass
> render_pass
= RenderPass::Create();
243 GetQuads(render_pass
.get(),
246 LayerTilingData::NO_BORDER_TEXELS
,
247 visible_content_rect
);
248 LayerTestCommon::VerifyQuadsExactlyCoverRect(render_pass
->quad_list
,
249 visible_content_rect
);
252 WITH_AND_WITHOUT_BORDER_TEST(CoverageVisibleRectOnTileBoundaries
);
254 WITH_AND_WITHOUT_BORDER_TEST(CoverageVisibleRectIntersectsTiles
);
256 WITH_AND_WITHOUT_BORDER_TEST(CoverageVisibleRectIntersectsBounds
);
258 TEST_F(TiledLayerImplTest
, TextureInfoForLayerNoBorders
) {
259 gfx::Size
tile_size(50, 50);
260 gfx::Size
layer_size(250, 250);
261 scoped_ptr
<RenderPass
> render_pass
= RenderPass::Create();
262 GetQuads(render_pass
.get(),
265 LayerTilingData::NO_BORDER_TEXELS
,
266 gfx::Rect(layer_size
));
268 for (auto iter
= render_pass
->quad_list
.cbegin();
269 iter
!= render_pass
->quad_list
.cend();
271 const TileDrawQuad
* quad
= TileDrawQuad::MaterialCast(*iter
);
273 EXPECT_NE(0u, quad
->resource_id
) << LayerTestCommon::quad_string
275 EXPECT_EQ(gfx::RectF(gfx::PointF(), tile_size
), quad
->tex_coord_rect
)
276 << LayerTestCommon::quad_string
<< iter
.index();
277 EXPECT_EQ(tile_size
, quad
->texture_size
) << LayerTestCommon::quad_string
282 TEST_F(TiledLayerImplTest
, GPUMemoryUsage
) {
283 gfx::Size
tile_size(20, 30);
284 int num_tiles_x
= 12;
285 int num_tiles_y
= 32;
286 gfx::Size
layer_size(tile_size
.width() * num_tiles_x
,
287 tile_size
.height() * num_tiles_y
);
289 scoped_ptr
<TiledLayerImpl
> layer
= CreateLayerNoTiles(
290 tile_size
, layer_size
, LayerTilingData::NO_BORDER_TEXELS
);
292 EXPECT_EQ(layer
->GPUMemoryUsageInBytes(), 0u);
294 ResourceProvider::ResourceId resource_id
= 1;
295 layer
->PushTileProperties(0, 1, resource_id
++, false);
296 layer
->PushTileProperties(2, 3, resource_id
++, false);
297 layer
->PushTileProperties(2, 0, resource_id
++, false);
300 layer
->GPUMemoryUsageInBytes(),
301 static_cast<size_t>(3 * 4 * tile_size
.width() * tile_size
.height()));
303 ResourceProvider::ResourceId
empty_resource(0);
304 layer
->PushTileProperties(0, 1, empty_resource
, false);
305 layer
->PushTileProperties(2, 3, empty_resource
, false);
306 layer
->PushTileProperties(2, 0, empty_resource
, false);
308 EXPECT_EQ(layer
->GPUMemoryUsageInBytes(), 0u);
311 TEST_F(TiledLayerImplTest
, EmptyMask
) {
312 gfx::Size
tile_size(20, 20);
313 gfx::Size
layer_size(0, 0);
314 scoped_ptr
<TiledLayerImpl
> layer
=
315 CreateLayer(tile_size
, layer_size
, LayerTilingData::NO_BORDER_TEXELS
);
317 ResourceProvider::ResourceId mask_resource_id
;
318 gfx::Size mask_texture_size
;
319 layer
->GetContentsResourceId(&mask_resource_id
, &mask_texture_size
);
320 EXPECT_EQ(0u, mask_resource_id
);
321 EXPECT_EQ(0, layer
->TilingForTesting()->num_tiles_x());
322 EXPECT_EQ(0, layer
->TilingForTesting()->num_tiles_y());
325 TEST_F(TiledLayerImplTest
, Occlusion
) {
326 gfx::Size
tile_size(100, 100);
327 gfx::Size
layer_bounds(1000, 1000);
328 gfx::Size
viewport_size(1000, 1000);
330 LayerTestCommon::LayerImplTest impl
;
332 TiledLayerImpl
* tiled_layer
= impl
.AddChildToRoot
<TiledLayerImpl
>();
333 tiled_layer
->SetBounds(layer_bounds
);
334 tiled_layer
->SetContentBounds(layer_bounds
);
335 tiled_layer
->SetDrawsContent(true);
336 tiled_layer
->set_skips_draw(false);
338 scoped_ptr
<LayerTilingData
> tiler
=
339 LayerTilingData::Create(tile_size
, LayerTilingData::NO_BORDER_TEXELS
);
340 tiler
->SetTilingSize(layer_bounds
);
341 tiled_layer
->SetTilingData(*tiler
);
343 for (int i
= 0; i
< tiled_layer
->TilingForTesting()->num_tiles_x(); ++i
) {
344 for (int j
= 0; j
< tiled_layer
->TilingForTesting()->num_tiles_y(); ++j
) {
345 ResourceProvider::ResourceId resource_id
=
346 impl
.resource_provider()->CreateResource(
347 gfx::Size(1, 1), GL_CLAMP_TO_EDGE
,
348 ResourceProvider::TEXTURE_HINT_IMMUTABLE
, RGBA_8888
);
349 tiled_layer
->PushTileProperties(i
, j
, resource_id
, false);
353 impl
.CalcDrawProps(viewport_size
);
356 SCOPED_TRACE("No occlusion");
358 impl
.AppendQuadsWithOcclusion(tiled_layer
, occluded
);
360 LayerTestCommon::VerifyQuadsExactlyCoverRect(impl
.quad_list(),
361 gfx::Rect(layer_bounds
));
362 EXPECT_EQ(100u, impl
.quad_list().size());
366 SCOPED_TRACE("Full occlusion");
367 gfx::Rect
occluded(tiled_layer
->visible_content_rect());
368 impl
.AppendQuadsWithOcclusion(tiled_layer
, occluded
);
370 LayerTestCommon::VerifyQuadsExactlyCoverRect(impl
.quad_list(), gfx::Rect());
371 EXPECT_EQ(impl
.quad_list().size(), 0u);
375 SCOPED_TRACE("Partial occlusion");
376 gfx::Rect
occluded(150, 0, 200, 1000);
377 impl
.AppendQuadsWithOcclusion(tiled_layer
, occluded
);
379 size_t partially_occluded_count
= 0;
380 LayerTestCommon::VerifyQuadsAreOccluded(
381 impl
.quad_list(), occluded
, &partially_occluded_count
);
382 // The layer outputs one quad, which is partially occluded.
383 EXPECT_EQ(100u - 10u, impl
.quad_list().size());
384 EXPECT_EQ(10u + 10u, partially_occluded_count
);