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 |