• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/mock_quad_culler.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:
TiledLayerImplTest()23   TiledLayerImplTest() : host_impl_(&proxy_, &shared_bitmap_manager_) {}
24 
CreateLayerNoTiles(const gfx::Size & tile_size,const gfx::Size & layer_size,LayerTilingData::BorderTexelOption border_texels)25   scoped_ptr<TiledLayerImpl> CreateLayerNoTiles(
26       const gfx::Size& tile_size,
27       const gfx::Size& layer_size,
28       LayerTilingData::BorderTexelOption border_texels) {
29     scoped_ptr<TiledLayerImpl> layer =
30         TiledLayerImpl::Create(host_impl_.active_tree(), 1);
31     scoped_ptr<LayerTilingData> tiler =
32         LayerTilingData::Create(tile_size, border_texels);
33     tiler->SetTilingRect(gfx::Rect(layer_size));
34     layer->SetTilingData(*tiler);
35     layer->set_skips_draw(false);
36     layer->draw_properties().visible_content_rect =
37         gfx::Rect(layer_size);
38     layer->draw_properties().opacity = 1;
39     layer->SetBounds(layer_size);
40     layer->SetContentBounds(layer_size);
41     layer->CreateRenderSurface();
42     layer->draw_properties().render_target = layer.get();
43     return layer.Pass();
44   }
45 
46   // Create a default tiled layer with textures for all tiles and a default
47   // visibility of the entire layer size.
CreateLayer(const gfx::Size & tile_size,const gfx::Size & layer_size,LayerTilingData::BorderTexelOption border_texels)48   scoped_ptr<TiledLayerImpl> CreateLayer(
49       const gfx::Size& tile_size,
50       const gfx::Size& layer_size,
51       LayerTilingData::BorderTexelOption border_texels) {
52     scoped_ptr<TiledLayerImpl> layer =
53         CreateLayerNoTiles(tile_size, layer_size, border_texels);
54 
55     ResourceProvider::ResourceId resource_id = 1;
56     for (int i = 0; i < layer->TilingForTesting()->num_tiles_x(); ++i) {
57       for (int j = 0; j < layer->TilingForTesting()->num_tiles_y(); ++j) {
58         gfx::Rect opaque_rect(
59             layer->TilingForTesting()->tile_bounds(i, j).origin(),
60             gfx::Size(1, 1));
61         layer->PushTileProperties(i, j, resource_id++, opaque_rect, false);
62       }
63     }
64 
65     return layer.Pass();
66   }
67 
GetQuads(RenderPass * render_pass,const gfx::Size & tile_size,const gfx::Size & layer_size,LayerTilingData::BorderTexelOption border_texel_option,const gfx::Rect & visible_content_rect)68   void GetQuads(RenderPass* render_pass,
69                 const gfx::Size& tile_size,
70                 const gfx::Size& layer_size,
71                 LayerTilingData::BorderTexelOption border_texel_option,
72                 const gfx::Rect& visible_content_rect) {
73     scoped_ptr<TiledLayerImpl> layer =
74         CreateLayer(tile_size, layer_size, border_texel_option);
75     layer->draw_properties().visible_content_rect = visible_content_rect;
76     layer->SetBounds(layer_size);
77 
78     MockOcclusionTracker<LayerImpl> occlusion_tracker;
79     MockQuadCuller quad_culler(render_pass, &occlusion_tracker);
80     AppendQuadsData data;
81     layer->AppendQuads(&quad_culler, &data);
82   }
83 
84  protected:
85   FakeImplProxy proxy_;
86   TestSharedBitmapManager shared_bitmap_manager_;
87   FakeLayerTreeHostImpl host_impl_;
88 };
89 
TEST_F(TiledLayerImplTest,EmptyQuadList)90 TEST_F(TiledLayerImplTest, EmptyQuadList) {
91   gfx::Size tile_size(90, 90);
92   int num_tiles_x = 8;
93   int num_tiles_y = 4;
94   gfx::Size layer_size(tile_size.width() * num_tiles_x,
95                        tile_size.height() * num_tiles_y);
96 
97   // Verify default layer does creates quads
98   {
99     scoped_ptr<TiledLayerImpl> layer =
100         CreateLayer(tile_size, layer_size, LayerTilingData::NO_BORDER_TEXELS);
101     MockOcclusionTracker<LayerImpl> occlusion_tracker;
102     scoped_ptr<RenderPass> render_pass = RenderPass::Create();
103     MockQuadCuller quad_culler(render_pass.get(), &occlusion_tracker);
104 
105     AppendQuadsData data;
106     EXPECT_TRUE(layer->WillDraw(DRAW_MODE_HARDWARE, NULL));
107     layer->AppendQuads(&quad_culler, &data);
108     layer->DidDraw(NULL);
109     unsigned num_tiles = num_tiles_x * num_tiles_y;
110     EXPECT_EQ(quad_culler.quad_list().size(), num_tiles);
111   }
112 
113   // Layer with empty visible layer rect produces no quads
114   {
115     scoped_ptr<TiledLayerImpl> layer =
116         CreateLayer(tile_size, layer_size, LayerTilingData::NO_BORDER_TEXELS);
117     layer->draw_properties().visible_content_rect = gfx::Rect();
118 
119     MockOcclusionTracker<LayerImpl> occlusion_tracker;
120     scoped_ptr<RenderPass> render_pass = RenderPass::Create();
121     MockQuadCuller quad_culler(render_pass.get(), &occlusion_tracker);
122 
123     EXPECT_FALSE(layer->WillDraw(DRAW_MODE_HARDWARE, NULL));
124   }
125 
126   // Layer with non-intersecting visible layer rect produces no quads
127   {
128     scoped_ptr<TiledLayerImpl> layer =
129         CreateLayer(tile_size, layer_size, LayerTilingData::NO_BORDER_TEXELS);
130 
131     gfx::Rect outside_bounds(-100, -100, 50, 50);
132     layer->draw_properties().visible_content_rect = outside_bounds;
133 
134     MockOcclusionTracker<LayerImpl> occlusion_tracker;
135     scoped_ptr<RenderPass> render_pass = RenderPass::Create();
136     MockQuadCuller quad_culler(render_pass.get(), &occlusion_tracker);
137 
138     AppendQuadsData data;
139     EXPECT_TRUE(layer->WillDraw(DRAW_MODE_HARDWARE, NULL));
140     layer->AppendQuads(&quad_culler, &data);
141     layer->DidDraw(NULL);
142     EXPECT_EQ(quad_culler.quad_list().size(), 0u);
143   }
144 
145   // Layer with skips draw produces no quads
146   {
147     scoped_ptr<TiledLayerImpl> layer =
148         CreateLayer(tile_size, layer_size, LayerTilingData::NO_BORDER_TEXELS);
149     layer->set_skips_draw(true);
150 
151     MockOcclusionTracker<LayerImpl> occlusion_tracker;
152     scoped_ptr<RenderPass> render_pass = RenderPass::Create();
153     MockQuadCuller quad_culler(render_pass.get(), &occlusion_tracker);
154 
155     AppendQuadsData data;
156     layer->AppendQuads(&quad_culler, &data);
157     EXPECT_EQ(quad_culler.quad_list().size(), 0u);
158   }
159 }
160 
TEST_F(TiledLayerImplTest,Checkerboarding)161 TEST_F(TiledLayerImplTest, Checkerboarding) {
162   gfx::Size tile_size(10, 10);
163   int num_tiles_x = 2;
164   int num_tiles_y = 2;
165   gfx::Size layer_size(tile_size.width() * num_tiles_x,
166                        tile_size.height() * num_tiles_y);
167 
168   scoped_ptr<TiledLayerImpl> layer =
169       CreateLayer(tile_size, layer_size, LayerTilingData::NO_BORDER_TEXELS);
170 
171   // No checkerboarding
172   {
173     MockOcclusionTracker<LayerImpl> occlusion_tracker;
174     scoped_ptr<RenderPass> render_pass = RenderPass::Create();
175     MockQuadCuller quad_culler(render_pass.get(), &occlusion_tracker);
176 
177     AppendQuadsData data;
178     layer->AppendQuads(&quad_culler, &data);
179     EXPECT_EQ(quad_culler.quad_list().size(), 4u);
180     EXPECT_EQ(0u, data.num_missing_tiles);
181 
182     for (size_t i = 0; i < quad_culler.quad_list().size(); ++i)
183       EXPECT_EQ(quad_culler.quad_list()[i]->material, DrawQuad::TILED_CONTENT);
184   }
185 
186   for (int i = 0; i < num_tiles_x; ++i)
187     for (int j = 0; j < num_tiles_y; ++j)
188       layer->PushTileProperties(i, j, 0, gfx::Rect(), false);
189 
190   // All checkerboarding
191   {
192     MockOcclusionTracker<LayerImpl> occlusion_tracker;
193     scoped_ptr<RenderPass> render_pass = RenderPass::Create();
194     MockQuadCuller quad_culler(render_pass.get(), &occlusion_tracker);
195 
196     AppendQuadsData data;
197     layer->AppendQuads(&quad_culler, &data);
198     EXPECT_LT(0u, data.num_missing_tiles);
199     EXPECT_EQ(quad_culler.quad_list().size(), 4u);
200     for (size_t i = 0; i < quad_culler.quad_list().size(); ++i)
201       EXPECT_NE(quad_culler.quad_list()[i]->material, DrawQuad::TILED_CONTENT);
202   }
203 }
204 
205 // Test with both border texels and without.
206 #define WITH_AND_WITHOUT_BORDER_TEST(text_fixture_name)                        \
207   TEST_F(TiledLayerImplBorderTest, text_fixture_name##NoBorders) {             \
208     text_fixture_name(LayerTilingData::NO_BORDER_TEXELS);                      \
209   }                                                                            \
210   TEST_F(TiledLayerImplBorderTest, text_fixture_name##HasBorders) {            \
211     text_fixture_name(LayerTilingData::HAS_BORDER_TEXELS);                     \
212   }
213 
214 class TiledLayerImplBorderTest : public TiledLayerImplTest {
215  public:
CoverageVisibleRectOnTileBoundaries(LayerTilingData::BorderTexelOption borders)216   void CoverageVisibleRectOnTileBoundaries(
217       LayerTilingData::BorderTexelOption borders) {
218     gfx::Size layer_size(1000, 1000);
219     scoped_ptr<RenderPass> render_pass = RenderPass::Create();
220     GetQuads(render_pass.get(),
221              gfx::Size(100, 100),
222              layer_size,
223              borders,
224              gfx::Rect(layer_size));
225     LayerTestCommon::VerifyQuadsExactlyCoverRect(render_pass->quad_list,
226                                                  gfx::Rect(layer_size));
227   }
228 
CoverageVisibleRectIntersectsTiles(LayerTilingData::BorderTexelOption borders)229   void CoverageVisibleRectIntersectsTiles(
230       LayerTilingData::BorderTexelOption borders) {
231     // This rect intersects the middle 3x3 of the 5x5 tiles.
232     gfx::Point top_left(65, 73);
233     gfx::Point bottom_right(182, 198);
234     gfx::Rect visible_content_rect = gfx::BoundingRect(top_left, bottom_right);
235 
236     gfx::Size layer_size(250, 250);
237     scoped_ptr<RenderPass> render_pass = RenderPass::Create();
238     GetQuads(render_pass.get(),
239              gfx::Size(50, 50),
240              gfx::Size(250, 250),
241              LayerTilingData::NO_BORDER_TEXELS,
242              visible_content_rect);
243     LayerTestCommon::VerifyQuadsExactlyCoverRect(render_pass->quad_list,
244                                                  visible_content_rect);
245   }
246 
CoverageVisibleRectIntersectsBounds(LayerTilingData::BorderTexelOption borders)247   void CoverageVisibleRectIntersectsBounds(
248       LayerTilingData::BorderTexelOption borders) {
249     gfx::Size layer_size(220, 210);
250     gfx::Rect visible_content_rect(layer_size);
251     scoped_ptr<RenderPass> render_pass = RenderPass::Create();
252     GetQuads(render_pass.get(),
253              gfx::Size(100, 100),
254              layer_size,
255              LayerTilingData::NO_BORDER_TEXELS,
256              visible_content_rect);
257     LayerTestCommon::VerifyQuadsExactlyCoverRect(render_pass->quad_list,
258                                                  visible_content_rect);
259   }
260 };
261 WITH_AND_WITHOUT_BORDER_TEST(CoverageVisibleRectOnTileBoundaries);
262 
263 WITH_AND_WITHOUT_BORDER_TEST(CoverageVisibleRectIntersectsTiles);
264 
265 WITH_AND_WITHOUT_BORDER_TEST(CoverageVisibleRectIntersectsBounds);
266 
TEST_F(TiledLayerImplTest,TextureInfoForLayerNoBorders)267 TEST_F(TiledLayerImplTest, TextureInfoForLayerNoBorders) {
268   gfx::Size tile_size(50, 50);
269   gfx::Size layer_size(250, 250);
270   scoped_ptr<RenderPass> render_pass = RenderPass::Create();
271   GetQuads(render_pass.get(),
272            tile_size,
273            layer_size,
274            LayerTilingData::NO_BORDER_TEXELS,
275            gfx::Rect(layer_size));
276 
277   for (size_t i = 0; i < render_pass->quad_list.size(); ++i) {
278     const TileDrawQuad* quad =
279         TileDrawQuad::MaterialCast(render_pass->quad_list[i]);
280 
281     EXPECT_NE(0u, quad->resource_id) << LayerTestCommon::quad_string << i;
282     EXPECT_EQ(gfx::RectF(gfx::PointF(), tile_size), quad->tex_coord_rect)
283         << LayerTestCommon::quad_string << i;
284     EXPECT_EQ(tile_size, quad->texture_size) << LayerTestCommon::quad_string
285                                              << i;
286     EXPECT_EQ(gfx::Size(1, 1).ToString(), quad->opaque_rect.size().ToString())
287         << LayerTestCommon::quad_string << i;
288   }
289 }
290 
TEST_F(TiledLayerImplTest,GPUMemoryUsage)291 TEST_F(TiledLayerImplTest, GPUMemoryUsage) {
292   gfx::Size tile_size(20, 30);
293   int num_tiles_x = 12;
294   int num_tiles_y = 32;
295   gfx::Size layer_size(tile_size.width() * num_tiles_x,
296                        tile_size.height() * num_tiles_y);
297 
298   scoped_ptr<TiledLayerImpl> layer = CreateLayerNoTiles(
299       tile_size, layer_size, LayerTilingData::NO_BORDER_TEXELS);
300 
301   EXPECT_EQ(layer->GPUMemoryUsageInBytes(), 0u);
302 
303   ResourceProvider::ResourceId resource_id = 1;
304   layer->PushTileProperties(0, 1, resource_id++, gfx::Rect(0, 0, 1, 1), false);
305   layer->PushTileProperties(2, 3, resource_id++, gfx::Rect(0, 0, 1, 1), false);
306   layer->PushTileProperties(2, 0, resource_id++, gfx::Rect(0, 0, 1, 1), false);
307 
308   EXPECT_EQ(
309       layer->GPUMemoryUsageInBytes(),
310       static_cast<size_t>(3 * 4 * tile_size.width() * tile_size.height()));
311 
312   ResourceProvider::ResourceId empty_resource(0);
313   layer->PushTileProperties(0, 1, empty_resource, gfx::Rect(0, 0, 1, 1), false);
314   layer->PushTileProperties(2, 3, empty_resource, gfx::Rect(0, 0, 1, 1), false);
315   layer->PushTileProperties(2, 0, empty_resource, gfx::Rect(0, 0, 1, 1), false);
316 
317   EXPECT_EQ(layer->GPUMemoryUsageInBytes(), 0u);
318 }
319 
TEST_F(TiledLayerImplTest,EmptyMask)320 TEST_F(TiledLayerImplTest, EmptyMask) {
321   gfx::Size tile_size(20, 20);
322   gfx::Size layer_size(0, 0);
323   scoped_ptr<TiledLayerImpl> layer =
324       CreateLayer(tile_size, layer_size, LayerTilingData::NO_BORDER_TEXELS);
325 
326   EXPECT_EQ(0u, layer->ContentsResourceId());
327   EXPECT_EQ(0, layer->TilingForTesting()->num_tiles_x());
328   EXPECT_EQ(0, layer->TilingForTesting()->num_tiles_y());
329 }
330 
TEST_F(TiledLayerImplTest,Occlusion)331 TEST_F(TiledLayerImplTest, Occlusion) {
332   gfx::Size tile_size(100, 100);
333   gfx::Size layer_bounds(1000, 1000);
334   gfx::Size viewport_size(1000, 1000);
335 
336   LayerTestCommon::LayerImplTest impl;
337 
338   TiledLayerImpl* tiled_layer = impl.AddChildToRoot<TiledLayerImpl>();
339   tiled_layer->SetBounds(layer_bounds);
340   tiled_layer->SetContentBounds(layer_bounds);
341   tiled_layer->SetDrawsContent(true);
342   tiled_layer->set_skips_draw(false);
343 
344   scoped_ptr<LayerTilingData> tiler =
345       LayerTilingData::Create(tile_size, LayerTilingData::NO_BORDER_TEXELS);
346   tiler->SetTilingRect(gfx::Rect(layer_bounds));
347   tiled_layer->SetTilingData(*tiler);
348 
349   ResourceProvider::ResourceId resource_id = 1;
350   for (int i = 0; i < tiled_layer->TilingForTesting()->num_tiles_x(); ++i) {
351     for (int j = 0; j < tiled_layer->TilingForTesting()->num_tiles_y(); ++j)
352       tiled_layer->PushTileProperties(i, j, resource_id++, gfx::Rect(), false);
353   }
354 
355   impl.CalcDrawProps(viewport_size);
356 
357   {
358     SCOPED_TRACE("No occlusion");
359     gfx::Rect occluded;
360     impl.AppendQuadsWithOcclusion(tiled_layer, occluded);
361 
362     LayerTestCommon::VerifyQuadsExactlyCoverRect(impl.quad_list(),
363                                                  gfx::Rect(layer_bounds));
364     EXPECT_EQ(100u, impl.quad_list().size());
365   }
366 
367   {
368     SCOPED_TRACE("Full occlusion");
369     gfx::Rect occluded(tiled_layer->visible_content_rect());
370     impl.AppendQuadsWithOcclusion(tiled_layer, occluded);
371 
372     LayerTestCommon::VerifyQuadsExactlyCoverRect(impl.quad_list(), gfx::Rect());
373     EXPECT_EQ(impl.quad_list().size(), 0u);
374   }
375 
376   {
377     SCOPED_TRACE("Partial occlusion");
378     gfx::Rect occluded(150, 0, 200, 1000);
379     impl.AppendQuadsWithOcclusion(tiled_layer, occluded);
380 
381     size_t partially_occluded_count = 0;
382     LayerTestCommon::VerifyQuadsCoverRectWithOcclusion(
383         impl.quad_list(),
384         gfx::Rect(layer_bounds),
385         occluded,
386         &partially_occluded_count);
387     // The layer outputs one quad, which is partially occluded.
388     EXPECT_EQ(100u - 10u, impl.quad_list().size());
389     EXPECT_EQ(10u + 10u, partially_occluded_count);
390   }
391 }
392 
393 }  // namespace
394 }  // namespace cc
395