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_) {}
24
25  scoped_ptr<TiledLayerImpl> CreateLayerNoTiles(
26      gfx::Size tile_size,
27      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->SetBounds(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      gfx::Size tile_size,
50      gfx::Size layer_size,
51      LayerTilingData::BorderTexelOption border_texels) {
52    scoped_ptr<TiledLayerImpl> layer =
53        CreateLayerNoTiles(tile_size, layer_size, border_texels);
54
55    layer->SetDrawsContent(true);
56
57    ResourceProvider::ResourceId resource_id = 1;
58    for (int i = 0; i < layer->TilingForTesting()->num_tiles_x(); ++i) {
59      for (int j = 0; j < layer->TilingForTesting()->num_tiles_y(); ++j) {
60        gfx::Rect opaque_rect(
61            layer->TilingForTesting()->tile_bounds(i, j).origin(),
62            gfx::Size(1, 1));
63        layer->PushTileProperties(i, j, resource_id++, opaque_rect, false);
64      }
65    }
66
67    return layer.Pass();
68  }
69
70  void GetQuads(QuadList* quads,
71                SharedQuadStateList* shared_states,
72                gfx::Size tile_size,
73                gfx::Size layer_size,
74                LayerTilingData::BorderTexelOption border_texel_option,
75                gfx::Rect visible_content_rect) {
76    scoped_ptr<TiledLayerImpl> layer =
77        CreateLayer(tile_size, layer_size, border_texel_option);
78    layer->draw_properties().visible_content_rect = visible_content_rect;
79    layer->SetBounds(layer_size);
80
81    MockQuadCuller quad_culler(quads, shared_states);
82    AppendQuadsData data;
83    layer->AppendQuads(&quad_culler, &data);
84  }
85
86 protected:
87  FakeImplProxy proxy_;
88  FakeLayerTreeHostImpl host_impl_;
89};
90
91TEST_F(TiledLayerImplTest, EmptyQuadList) {
92  gfx::Size tile_size(90, 90);
93  int num_tiles_x = 8;
94  int num_tiles_y = 4;
95  gfx::Size layer_size(tile_size.width() * num_tiles_x,
96                       tile_size.height() * num_tiles_y);
97
98  // Verify default layer does creates quads
99  {
100    scoped_ptr<TiledLayerImpl> layer =
101        CreateLayer(tile_size, layer_size, LayerTilingData::NO_BORDER_TEXELS);
102    MockQuadCuller quad_culler;
103    AppendQuadsData data;
104    EXPECT_TRUE(layer->WillDraw(DRAW_MODE_HARDWARE, NULL));
105    layer->AppendQuads(&quad_culler, &data);
106    layer->DidDraw(NULL);
107    unsigned num_tiles = num_tiles_x * num_tiles_y;
108    EXPECT_EQ(quad_culler.quad_list().size(), num_tiles);
109  }
110
111  // Layer with empty visible layer rect produces no quads
112  {
113    scoped_ptr<TiledLayerImpl> layer =
114        CreateLayer(tile_size, layer_size, LayerTilingData::NO_BORDER_TEXELS);
115    layer->draw_properties().visible_content_rect = gfx::Rect();
116
117    MockQuadCuller quad_culler;
118    EXPECT_FALSE(layer->WillDraw(DRAW_MODE_HARDWARE, NULL));
119  }
120
121  // Layer with non-intersecting visible layer rect produces no quads
122  {
123    scoped_ptr<TiledLayerImpl> layer =
124        CreateLayer(tile_size, layer_size, LayerTilingData::NO_BORDER_TEXELS);
125
126    gfx::Rect outside_bounds(-100, -100, 50, 50);
127    layer->draw_properties().visible_content_rect = outside_bounds;
128
129    MockQuadCuller quad_culler;
130    AppendQuadsData data;
131    EXPECT_TRUE(layer->WillDraw(DRAW_MODE_HARDWARE, NULL));
132    layer->AppendQuads(&quad_culler, &data);
133    layer->DidDraw(NULL);
134    EXPECT_EQ(quad_culler.quad_list().size(), 0u);
135  }
136
137  // Layer with skips draw produces no quads
138  {
139    scoped_ptr<TiledLayerImpl> layer =
140        CreateLayer(tile_size, layer_size, LayerTilingData::NO_BORDER_TEXELS);
141    layer->set_skips_draw(true);
142
143    MockQuadCuller quad_culler;
144    AppendQuadsData data;
145    layer->AppendQuads(&quad_culler, &data);
146    EXPECT_EQ(quad_culler.quad_list().size(), 0u);
147  }
148}
149
150TEST_F(TiledLayerImplTest, Checkerboarding) {
151  gfx::Size tile_size(10, 10);
152  int num_tiles_x = 2;
153  int num_tiles_y = 2;
154  gfx::Size layer_size(tile_size.width() * num_tiles_x,
155                       tile_size.height() * num_tiles_y);
156
157  scoped_ptr<TiledLayerImpl> layer =
158      CreateLayer(tile_size, layer_size, LayerTilingData::NO_BORDER_TEXELS);
159
160  // No checkerboarding
161  {
162    MockQuadCuller quad_culler;
163    AppendQuadsData data;
164    layer->AppendQuads(&quad_culler, &data);
165    EXPECT_EQ(quad_culler.quad_list().size(), 4u);
166    EXPECT_EQ(0u, data.num_missing_tiles);
167
168    for (size_t i = 0; i < quad_culler.quad_list().size(); ++i)
169      EXPECT_EQ(quad_culler.quad_list()[i]->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, gfx::Rect(), false);
175
176  // All checkerboarding
177  {
178    MockQuadCuller quad_culler;
179    AppendQuadsData data;
180    layer->AppendQuads(&quad_culler, &data);
181    EXPECT_LT(0u, data.num_missing_tiles);
182    EXPECT_EQ(quad_culler.quad_list().size(), 4u);
183    for (size_t i = 0; i < quad_culler.quad_list().size(); ++i)
184      EXPECT_NE(quad_culler.quad_list()[i]->material, DrawQuad::TILED_CONTENT);
185  }
186}
187
188// Test with both border texels and without.
189#define WITH_AND_WITHOUT_BORDER_TEST(text_fixture_name)                        \
190  TEST_F(TiledLayerImplBorderTest, text_fixture_name##NoBorders) {             \
191    text_fixture_name(LayerTilingData::NO_BORDER_TEXELS);                      \
192  }                                                                            \
193  TEST_F(TiledLayerImplBorderTest, text_fixture_name##HasBorders) {            \
194    text_fixture_name(LayerTilingData::HAS_BORDER_TEXELS);                     \
195  }
196
197class TiledLayerImplBorderTest : public TiledLayerImplTest {
198 public:
199  void CoverageVisibleRectOnTileBoundaries(
200      LayerTilingData::BorderTexelOption borders) {
201    gfx::Size layer_size(1000, 1000);
202    QuadList quads;
203    SharedQuadStateList shared_states;
204    GetQuads(&quads,
205             &shared_states,
206             gfx::Size(100, 100),
207             layer_size,
208             borders,
209             gfx::Rect(layer_size));
210    LayerTestCommon::VerifyQuadsExactlyCoverRect(quads, 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    QuadList quads;
222    SharedQuadStateList shared_states;
223    GetQuads(&quads,
224             &shared_states,
225             gfx::Size(50, 50),
226             gfx::Size(250, 250),
227             LayerTilingData::NO_BORDER_TEXELS,
228             visible_content_rect);
229    LayerTestCommon::VerifyQuadsExactlyCoverRect(quads, visible_content_rect);
230  }
231
232  void CoverageVisibleRectIntersectsBounds(
233      LayerTilingData::BorderTexelOption borders) {
234    gfx::Size layer_size(220, 210);
235    gfx::Rect visible_content_rect(layer_size);
236    QuadList quads;
237    SharedQuadStateList shared_states;
238    GetQuads(&quads,
239             &shared_states,
240             gfx::Size(100, 100),
241             layer_size,
242             LayerTilingData::NO_BORDER_TEXELS,
243             visible_content_rect);
244    LayerTestCommon::VerifyQuadsExactlyCoverRect(quads, visible_content_rect);
245  }
246};
247WITH_AND_WITHOUT_BORDER_TEST(CoverageVisibleRectOnTileBoundaries);
248
249WITH_AND_WITHOUT_BORDER_TEST(CoverageVisibleRectIntersectsTiles);
250
251WITH_AND_WITHOUT_BORDER_TEST(CoverageVisibleRectIntersectsBounds);
252
253TEST_F(TiledLayerImplTest, TextureInfoForLayerNoBorders) {
254  gfx::Size tile_size(50, 50);
255  gfx::Size layer_size(250, 250);
256  QuadList quads;
257  SharedQuadStateList shared_states;
258  GetQuads(&quads,
259           &shared_states,
260           tile_size,
261           layer_size,
262           LayerTilingData::NO_BORDER_TEXELS,
263           gfx::Rect(layer_size));
264
265  for (size_t i = 0; i < quads.size(); ++i) {
266    const TileDrawQuad* quad = TileDrawQuad::MaterialCast(quads[i]);
267
268    EXPECT_NE(0u, quad->resource_id) << LayerTestCommon::quad_string << i;
269    EXPECT_EQ(gfx::RectF(gfx::PointF(), tile_size), quad->tex_coord_rect)
270        << LayerTestCommon::quad_string << i;
271    EXPECT_EQ(tile_size, quad->texture_size) << LayerTestCommon::quad_string
272                                             << i;
273    EXPECT_EQ(gfx::Size(1, 1).ToString(), quad->opaque_rect.size().ToString())
274        << LayerTestCommon::quad_string << i;
275  }
276}
277
278TEST_F(TiledLayerImplTest, GPUMemoryUsage) {
279  gfx::Size tile_size(20, 30);
280  int num_tiles_x = 12;
281  int num_tiles_y = 32;
282  gfx::Size layer_size(tile_size.width() * num_tiles_x,
283                       tile_size.height() * num_tiles_y);
284
285  scoped_ptr<TiledLayerImpl> layer = CreateLayerNoTiles(
286      tile_size, layer_size, LayerTilingData::NO_BORDER_TEXELS);
287
288  EXPECT_EQ(layer->GPUMemoryUsageInBytes(), 0u);
289
290  ResourceProvider::ResourceId resource_id = 1;
291  layer->PushTileProperties(0, 1, resource_id++, gfx::Rect(0, 0, 1, 1), false);
292  layer->PushTileProperties(2, 3, resource_id++, gfx::Rect(0, 0, 1, 1), false);
293  layer->PushTileProperties(2, 0, resource_id++, gfx::Rect(0, 0, 1, 1), false);
294
295  EXPECT_EQ(
296      layer->GPUMemoryUsageInBytes(),
297      static_cast<size_t>(3 * 4 * tile_size.width() * tile_size.height()));
298
299  ResourceProvider::ResourceId empty_resource(0);
300  layer->PushTileProperties(0, 1, empty_resource, gfx::Rect(0, 0, 1, 1), false);
301  layer->PushTileProperties(2, 3, empty_resource, gfx::Rect(0, 0, 1, 1), false);
302  layer->PushTileProperties(2, 0, empty_resource, gfx::Rect(0, 0, 1, 1), false);
303
304  EXPECT_EQ(layer->GPUMemoryUsageInBytes(), 0u);
305}
306
307}  // namespace
308}  // namespace cc
309