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
->SetTilingRect(gfx::Rect(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
->CreateRenderSurface();
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 gfx::Rect
opaque_rect(
58 layer
->TilingForTesting()->tile_bounds(i
, j
).origin(),
60 layer
->PushTileProperties(i
, j
, resource_id
++, opaque_rect
, false);
67 void GetQuads(RenderPass
* render_pass
,
68 const gfx::Size
& tile_size
,
69 const gfx::Size
& layer_size
,
70 LayerTilingData::BorderTexelOption border_texel_option
,
71 const gfx::Rect
& visible_content_rect
) {
72 scoped_ptr
<TiledLayerImpl
> layer
=
73 CreateLayer(tile_size
, layer_size
, border_texel_option
);
74 layer
->draw_properties().visible_content_rect
= visible_content_rect
;
75 layer
->SetBounds(layer_size
);
77 MockOcclusionTracker
<LayerImpl
> occlusion_tracker
;
79 layer
->AppendQuads(render_pass
, occlusion_tracker
, &data
);
84 TestSharedBitmapManager shared_bitmap_manager_
;
85 FakeLayerTreeHostImpl host_impl_
;
88 TEST_F(TiledLayerImplTest
, EmptyQuadList
) {
89 gfx::Size
tile_size(90, 90);
92 gfx::Size
layer_size(tile_size
.width() * num_tiles_x
,
93 tile_size
.height() * num_tiles_y
);
95 // Verify default layer does creates quads
97 scoped_ptr
<TiledLayerImpl
> layer
=
98 CreateLayer(tile_size
, layer_size
, LayerTilingData::NO_BORDER_TEXELS
);
99 MockOcclusionTracker
<LayerImpl
> occlusion_tracker
;
100 scoped_ptr
<RenderPass
> render_pass
= RenderPass::Create();
102 AppendQuadsData data
;
103 EXPECT_TRUE(layer
->WillDraw(DRAW_MODE_HARDWARE
, NULL
));
104 layer
->AppendQuads(render_pass
.get(), occlusion_tracker
, &data
);
105 layer
->DidDraw(NULL
);
106 unsigned num_tiles
= num_tiles_x
* num_tiles_y
;
107 EXPECT_EQ(render_pass
->quad_list
.size(), num_tiles
);
110 // Layer with empty visible layer rect produces no quads
112 scoped_ptr
<TiledLayerImpl
> layer
=
113 CreateLayer(tile_size
, layer_size
, LayerTilingData::NO_BORDER_TEXELS
);
114 layer
->draw_properties().visible_content_rect
= gfx::Rect();
116 MockOcclusionTracker
<LayerImpl
> occlusion_tracker
;
117 scoped_ptr
<RenderPass
> render_pass
= RenderPass::Create();
119 EXPECT_FALSE(layer
->WillDraw(DRAW_MODE_HARDWARE
, NULL
));
122 // Layer with non-intersecting visible layer rect produces no quads
124 scoped_ptr
<TiledLayerImpl
> layer
=
125 CreateLayer(tile_size
, layer_size
, LayerTilingData::NO_BORDER_TEXELS
);
127 gfx::Rect
outside_bounds(-100, -100, 50, 50);
128 layer
->draw_properties().visible_content_rect
= outside_bounds
;
130 MockOcclusionTracker
<LayerImpl
> occlusion_tracker
;
131 scoped_ptr
<RenderPass
> render_pass
= RenderPass::Create();
133 AppendQuadsData data
;
134 EXPECT_TRUE(layer
->WillDraw(DRAW_MODE_HARDWARE
, NULL
));
135 layer
->AppendQuads(render_pass
.get(), occlusion_tracker
, &data
);
136 layer
->DidDraw(NULL
);
137 EXPECT_EQ(render_pass
->quad_list
.size(), 0u);
140 // Layer with skips draw produces no quads
142 scoped_ptr
<TiledLayerImpl
> layer
=
143 CreateLayer(tile_size
, layer_size
, LayerTilingData::NO_BORDER_TEXELS
);
144 layer
->set_skips_draw(true);
146 MockOcclusionTracker
<LayerImpl
> occlusion_tracker
;
147 scoped_ptr
<RenderPass
> render_pass
= RenderPass::Create();
149 AppendQuadsData data
;
150 layer
->AppendQuads(render_pass
.get(), occlusion_tracker
, &data
);
151 EXPECT_EQ(render_pass
->quad_list
.size(), 0u);
155 TEST_F(TiledLayerImplTest
, Checkerboarding
) {
156 gfx::Size
tile_size(10, 10);
159 gfx::Size
layer_size(tile_size
.width() * num_tiles_x
,
160 tile_size
.height() * num_tiles_y
);
162 scoped_ptr
<TiledLayerImpl
> layer
=
163 CreateLayer(tile_size
, layer_size
, LayerTilingData::NO_BORDER_TEXELS
);
165 // No checkerboarding
167 MockOcclusionTracker
<LayerImpl
> occlusion_tracker
;
168 scoped_ptr
<RenderPass
> render_pass
= RenderPass::Create();
170 AppendQuadsData data
;
171 layer
->AppendQuads(render_pass
.get(), occlusion_tracker
, &data
);
172 EXPECT_EQ(render_pass
->quad_list
.size(), 4u);
173 EXPECT_EQ(0u, data
.num_missing_tiles
);
175 for (size_t i
= 0; i
< render_pass
->quad_list
.size(); ++i
)
176 EXPECT_EQ(render_pass
->quad_list
[i
]->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, gfx::Rect(), false);
183 // All checkerboarding
185 MockOcclusionTracker
<LayerImpl
> occlusion_tracker
;
186 scoped_ptr
<RenderPass
> render_pass
= RenderPass::Create();
188 AppendQuadsData data
;
189 layer
->AppendQuads(render_pass
.get(), occlusion_tracker
, &data
);
190 EXPECT_LT(0u, data
.num_missing_tiles
);
191 EXPECT_EQ(render_pass
->quad_list
.size(), 4u);
192 for (size_t i
= 0; i
< render_pass
->quad_list
.size(); ++i
)
193 EXPECT_NE(render_pass
->quad_list
[i
]->material
, DrawQuad::TILED_CONTENT
);
197 // Test with both border texels and without.
198 #define WITH_AND_WITHOUT_BORDER_TEST(text_fixture_name) \
199 TEST_F(TiledLayerImplBorderTest, text_fixture_name##NoBorders) { \
200 text_fixture_name(LayerTilingData::NO_BORDER_TEXELS); \
202 TEST_F(TiledLayerImplBorderTest, text_fixture_name##HasBorders) { \
203 text_fixture_name(LayerTilingData::HAS_BORDER_TEXELS); \
206 class TiledLayerImplBorderTest
: public TiledLayerImplTest
{
208 void CoverageVisibleRectOnTileBoundaries(
209 LayerTilingData::BorderTexelOption borders
) {
210 gfx::Size
layer_size(1000, 1000);
211 scoped_ptr
<RenderPass
> render_pass
= RenderPass::Create();
212 GetQuads(render_pass
.get(),
216 gfx::Rect(layer_size
));
217 LayerTestCommon::VerifyQuadsExactlyCoverRect(render_pass
->quad_list
,
218 gfx::Rect(layer_size
));
221 void CoverageVisibleRectIntersectsTiles(
222 LayerTilingData::BorderTexelOption borders
) {
223 // This rect intersects the middle 3x3 of the 5x5 tiles.
224 gfx::Point
top_left(65, 73);
225 gfx::Point
bottom_right(182, 198);
226 gfx::Rect visible_content_rect
= gfx::BoundingRect(top_left
, bottom_right
);
228 gfx::Size
layer_size(250, 250);
229 scoped_ptr
<RenderPass
> render_pass
= RenderPass::Create();
230 GetQuads(render_pass
.get(),
233 LayerTilingData::NO_BORDER_TEXELS
,
234 visible_content_rect
);
235 LayerTestCommon::VerifyQuadsExactlyCoverRect(render_pass
->quad_list
,
236 visible_content_rect
);
239 void CoverageVisibleRectIntersectsBounds(
240 LayerTilingData::BorderTexelOption borders
) {
241 gfx::Size
layer_size(220, 210);
242 gfx::Rect
visible_content_rect(layer_size
);
243 scoped_ptr
<RenderPass
> render_pass
= RenderPass::Create();
244 GetQuads(render_pass
.get(),
247 LayerTilingData::NO_BORDER_TEXELS
,
248 visible_content_rect
);
249 LayerTestCommon::VerifyQuadsExactlyCoverRect(render_pass
->quad_list
,
250 visible_content_rect
);
253 WITH_AND_WITHOUT_BORDER_TEST(CoverageVisibleRectOnTileBoundaries
);
255 WITH_AND_WITHOUT_BORDER_TEST(CoverageVisibleRectIntersectsTiles
);
257 WITH_AND_WITHOUT_BORDER_TEST(CoverageVisibleRectIntersectsBounds
);
259 TEST_F(TiledLayerImplTest
, TextureInfoForLayerNoBorders
) {
260 gfx::Size
tile_size(50, 50);
261 gfx::Size
layer_size(250, 250);
262 scoped_ptr
<RenderPass
> render_pass
= RenderPass::Create();
263 GetQuads(render_pass
.get(),
266 LayerTilingData::NO_BORDER_TEXELS
,
267 gfx::Rect(layer_size
));
269 for (size_t i
= 0; i
< render_pass
->quad_list
.size(); ++i
) {
270 const TileDrawQuad
* quad
=
271 TileDrawQuad::MaterialCast(render_pass
->quad_list
[i
]);
273 EXPECT_NE(0u, quad
->resource_id
) << LayerTestCommon::quad_string
<< i
;
274 EXPECT_EQ(gfx::RectF(gfx::PointF(), tile_size
), quad
->tex_coord_rect
)
275 << LayerTestCommon::quad_string
<< i
;
276 EXPECT_EQ(tile_size
, quad
->texture_size
) << LayerTestCommon::quad_string
278 EXPECT_EQ(gfx::Size(1, 1).ToString(), quad
->opaque_rect
.size().ToString())
279 << LayerTestCommon::quad_string
<< i
;
283 TEST_F(TiledLayerImplTest
, GPUMemoryUsage
) {
284 gfx::Size
tile_size(20, 30);
285 int num_tiles_x
= 12;
286 int num_tiles_y
= 32;
287 gfx::Size
layer_size(tile_size
.width() * num_tiles_x
,
288 tile_size
.height() * num_tiles_y
);
290 scoped_ptr
<TiledLayerImpl
> layer
= CreateLayerNoTiles(
291 tile_size
, layer_size
, LayerTilingData::NO_BORDER_TEXELS
);
293 EXPECT_EQ(layer
->GPUMemoryUsageInBytes(), 0u);
295 ResourceProvider::ResourceId resource_id
= 1;
296 layer
->PushTileProperties(0, 1, resource_id
++, gfx::Rect(0, 0, 1, 1), false);
297 layer
->PushTileProperties(2, 3, resource_id
++, gfx::Rect(0, 0, 1, 1), false);
298 layer
->PushTileProperties(2, 0, resource_id
++, gfx::Rect(0, 0, 1, 1), false);
301 layer
->GPUMemoryUsageInBytes(),
302 static_cast<size_t>(3 * 4 * tile_size
.width() * tile_size
.height()));
304 ResourceProvider::ResourceId
empty_resource(0);
305 layer
->PushTileProperties(0, 1, empty_resource
, gfx::Rect(0, 0, 1, 1), false);
306 layer
->PushTileProperties(2, 3, empty_resource
, gfx::Rect(0, 0, 1, 1), false);
307 layer
->PushTileProperties(2, 0, empty_resource
, gfx::Rect(0, 0, 1, 1), false);
309 EXPECT_EQ(layer
->GPUMemoryUsageInBytes(), 0u);
312 TEST_F(TiledLayerImplTest
, EmptyMask
) {
313 gfx::Size
tile_size(20, 20);
314 gfx::Size
layer_size(0, 0);
315 scoped_ptr
<TiledLayerImpl
> layer
=
316 CreateLayer(tile_size
, layer_size
, LayerTilingData::NO_BORDER_TEXELS
);
318 EXPECT_EQ(0u, layer
->ContentsResourceId());
319 EXPECT_EQ(0, layer
->TilingForTesting()->num_tiles_x());
320 EXPECT_EQ(0, layer
->TilingForTesting()->num_tiles_y());
323 TEST_F(TiledLayerImplTest
, Occlusion
) {
324 gfx::Size
tile_size(100, 100);
325 gfx::Size
layer_bounds(1000, 1000);
326 gfx::Size
viewport_size(1000, 1000);
328 LayerTestCommon::LayerImplTest impl
;
330 TiledLayerImpl
* tiled_layer
= impl
.AddChildToRoot
<TiledLayerImpl
>();
331 tiled_layer
->SetBounds(layer_bounds
);
332 tiled_layer
->SetContentBounds(layer_bounds
);
333 tiled_layer
->SetDrawsContent(true);
334 tiled_layer
->set_skips_draw(false);
336 scoped_ptr
<LayerTilingData
> tiler
=
337 LayerTilingData::Create(tile_size
, LayerTilingData::NO_BORDER_TEXELS
);
338 tiler
->SetTilingRect(gfx::Rect(layer_bounds
));
339 tiled_layer
->SetTilingData(*tiler
);
341 ResourceProvider::ResourceId resource_id
= 1;
342 for (int i
= 0; i
< tiled_layer
->TilingForTesting()->num_tiles_x(); ++i
) {
343 for (int j
= 0; j
< tiled_layer
->TilingForTesting()->num_tiles_y(); ++j
)
344 tiled_layer
->PushTileProperties(i
, j
, resource_id
++, gfx::Rect(), false);
347 impl
.CalcDrawProps(viewport_size
);
350 SCOPED_TRACE("No occlusion");
352 impl
.AppendQuadsWithOcclusion(tiled_layer
, occluded
);
354 LayerTestCommon::VerifyQuadsExactlyCoverRect(impl
.quad_list(),
355 gfx::Rect(layer_bounds
));
356 EXPECT_EQ(100u, impl
.quad_list().size());
360 SCOPED_TRACE("Full occlusion");
361 gfx::Rect
occluded(tiled_layer
->visible_content_rect());
362 impl
.AppendQuadsWithOcclusion(tiled_layer
, occluded
);
364 LayerTestCommon::VerifyQuadsExactlyCoverRect(impl
.quad_list(), gfx::Rect());
365 EXPECT_EQ(impl
.quad_list().size(), 0u);
369 SCOPED_TRACE("Partial occlusion");
370 gfx::Rect
occluded(150, 0, 200, 1000);
371 impl
.AppendQuadsWithOcclusion(tiled_layer
, occluded
);
373 size_t partially_occluded_count
= 0;
374 LayerTestCommon::VerifyQuadsCoverRectWithOcclusion(
376 gfx::Rect(layer_bounds
),
378 &partially_occluded_count
);
379 // The layer outputs one quad, which is partially occluded.
380 EXPECT_EQ(100u - 10u, impl
.quad_list().size());
381 EXPECT_EQ(10u + 10u, partially_occluded_count
);