tiled_layer_impl_unittest.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
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
18namespace cc {
19namespace {
20
21class TiledLayerImplTest : public testing::Test {
22 public:
23  TiledLayerImplTest() : host_impl_(&proxy_, &shared_bitmap_manager_) {}
24
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.
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
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
90TEST_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
161TEST_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
214class TiledLayerImplBorderTest : public TiledLayerImplTest {
215 public:
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
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
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};
261WITH_AND_WITHOUT_BORDER_TEST(CoverageVisibleRectOnTileBoundaries);
262
263WITH_AND_WITHOUT_BORDER_TEST(CoverageVisibleRectIntersectsTiles);
264
265WITH_AND_WITHOUT_BORDER_TEST(CoverageVisibleRectIntersectsBounds);
266
267TEST_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
291TEST_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
320TEST_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
331TEST_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