blob: 881055f3efb14dd62af4bb188b1ef196972178ea [file] [log] [blame]
James Robinson646469d2014-10-03 15:33:28 -07001// Copyright 2013 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 <map>
6#include <utility>
7
8#include "cc/resources/picture_pile.h"
9#include "cc/test/fake_content_layer_client.h"
10#include "cc/test/fake_rendering_stats_instrumentation.h"
11#include "testing/gtest/include/gtest/gtest.h"
12#include "ui/gfx/rect_conversions.h"
13#include "ui/gfx/size_conversions.h"
14
15namespace cc {
16namespace {
17
18class TestPicturePile : public PicturePile {
19 public:
20 using PicturePile::buffer_pixels;
21 using PicturePile::CanRasterSlowTileCheck;
22 using PicturePile::Clear;
23
24 PictureMap& picture_map() { return picture_map_; }
25 const gfx::Rect& recorded_viewport() const { return recorded_viewport_; }
26
27 bool CanRasterLayerRect(const gfx::Rect& layer_rect) {
28 return CanRaster(1.f, layer_rect);
29 }
30
31 typedef PicturePile::PictureInfo PictureInfo;
32 typedef PicturePile::PictureMapKey PictureMapKey;
33 typedef PicturePile::PictureMap PictureMap;
34
35 protected:
James Robinsone1b30cf2014-10-21 12:25:40 -070036 ~TestPicturePile() override {}
James Robinson646469d2014-10-03 15:33:28 -070037};
38
39class PicturePileTestBase {
40 public:
41 PicturePileTestBase()
42 : background_color_(SK_ColorBLUE),
43 min_scale_(0.125),
44 frame_number_(0),
45 contents_opaque_(false) {}
46
47 void InitializeData() {
48 pile_ = make_scoped_refptr(new TestPicturePile());
49 pile_->SetTileGridSize(gfx::Size(1000, 1000));
50 pile_->SetMinContentsScale(min_scale_);
51 client_ = FakeContentLayerClient();
52 SetTilingSize(pile_->tiling().max_texture_size());
53 }
54
55 void SetTilingSize(const gfx::Size& tiling_size) {
56 Region invalidation;
57 gfx::Rect viewport_rect(tiling_size);
58 UpdateAndExpandInvalidation(&invalidation, tiling_size, viewport_rect);
59 }
60
61 gfx::Size tiling_size() const { return pile_->tiling_size(); }
62 gfx::Rect tiling_rect() const { return gfx::Rect(pile_->tiling_size()); }
63
64 bool UpdateAndExpandInvalidation(Region* invalidation,
65 const gfx::Size& layer_size,
66 const gfx::Rect& visible_layer_rect) {
67 frame_number_++;
68 return pile_->UpdateAndExpandInvalidation(&client_,
69 invalidation,
70 background_color_,
71 contents_opaque_,
72 false,
73 layer_size,
74 visible_layer_rect,
75 frame_number_,
76 Picture::RECORD_NORMALLY,
77 &stats_instrumentation_);
78 }
79
80 bool UpdateWholePile() {
81 Region invalidation = tiling_rect();
82 bool result = UpdateAndExpandInvalidation(
83 &invalidation, tiling_size(), tiling_rect());
84 EXPECT_EQ(tiling_rect().ToString(), invalidation.ToString());
85 return result;
86 }
87
88 FakeContentLayerClient client_;
89 FakeRenderingStatsInstrumentation stats_instrumentation_;
90 scoped_refptr<TestPicturePile> pile_;
91 SkColor background_color_;
92 float min_scale_;
93 int frame_number_;
94 bool contents_opaque_;
95};
96
97class PicturePileTest : public PicturePileTestBase, public testing::Test {
98 public:
James Robinsonbaf71d32014-10-08 13:00:20 -070099 virtual void SetUp() override { InitializeData(); }
James Robinson646469d2014-10-03 15:33:28 -0700100};
101
James Robinson80d418c2014-10-16 16:00:02 -0700102TEST_F(PicturePileTest, InvalidationOnTileBorderOutsideInterestRect) {
103 // Don't expand the interest rect past what we invalidate.
104 pile_->SetPixelRecordDistanceForTesting(0);
105
106 gfx::Size tile_size(100, 100);
107 pile_->tiling().SetMaxTextureSize(tile_size);
108
109 gfx::Size pile_size(400, 400);
110 SetTilingSize(pile_size);
111
112 // We have multiple tiles.
113 EXPECT_GT(pile_->tiling().num_tiles_x(), 2);
114 EXPECT_GT(pile_->tiling().num_tiles_y(), 2);
115
116 // Record everything.
117 Region invalidation(tiling_rect());
118 UpdateAndExpandInvalidation(&invalidation, tiling_size(), tiling_rect());
119
120 // +----------+-----------------+-----------+
121 // | | VVVV 1,0| |
122 // | | VVVV | |
123 // | | VVVV | |
124 // | ...|.................|... |
125 // | ...|.................|... |
126 // +----------+-----------------+-----------+
127 // | ...| |... |
128 // | ...| |... |
129 // | ...| |... |
130 // | ...| |... |
131 // | ...| 1,1|... |
132 // +----------+-----------------+-----------+
133 // | ...|.................|... |
134 // | ...|.................|... |
135 // +----------+-----------------+-----------+
136 //
137 // .. = border pixels for tile 1,1
138 // VV = interest rect (what we will record)
139 //
140 // The first invalidation is inside VV, so it does not touch border pixels of
141 // tile 1,1.
142 //
143 // The second invalidation goes below VV into the .. border pixels of 1,1.
144
145 // This is the VV interest rect which will be entirely inside 1,0 and not
146 // touch the border of 1,1.
147 gfx::Rect interest_rect(
148 pile_->tiling().TilePositionX(1) + pile_->tiling().border_texels(),
149 0,
150 10,
151 pile_->tiling().TileSizeY(0) - pile_->tiling().border_texels());
152
153 // Invalidate tile 1,0 only. This is a rect that avoids the borders of any
154 // other tiles.
155 gfx::Rect invalidate_tile = interest_rect;
156 // This should cause the tile 1,0 to be invalidated and re-recorded. The
157 // invalidation did not need to be expanded.
158 invalidation = invalidate_tile;
159 UpdateAndExpandInvalidation(&invalidation, tiling_size(), interest_rect);
160 EXPECT_EQ(invalidate_tile, invalidation);
161
162 // Invalidate tile 1,0 and 1,1 by invalidating something that only touches the
163 // border of 1,1 (and is inside the tile bounds of 1,0). This is a 10px wide
164 // strip from the top of the tiling onto the border pixels of tile 1,1 that
165 // avoids border pixels of any other tiles.
166 gfx::Rect invalidate_border = interest_rect;
167 invalidate_border.Inset(0, 0, 0, -1);
168 // This should cause the tile 1,0 and 1,1 to be invalidated. The 1,1 tile will
169 // not be re-recorded since it does not touch the interest rect, so the
170 // invalidation should be expanded to cover all of 1,1.
171 invalidation = invalidate_border;
172 UpdateAndExpandInvalidation(&invalidation, tiling_size(), interest_rect);
173 Region expected_invalidation = invalidate_border;
174 expected_invalidation.Union(pile_->tiling().TileBounds(1, 1));
175 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
176}
177
James Robinson646469d2014-10-03 15:33:28 -0700178TEST_F(PicturePileTest, SmallInvalidateInflated) {
179 // Invalidate something inside a tile.
180 Region invalidate_rect(gfx::Rect(50, 50, 1, 1));
181 UpdateAndExpandInvalidation(&invalidate_rect, tiling_size(), tiling_rect());
182 EXPECT_EQ(gfx::Rect(50, 50, 1, 1).ToString(), invalidate_rect.ToString());
183
184 EXPECT_EQ(1, pile_->tiling().num_tiles_x());
185 EXPECT_EQ(1, pile_->tiling().num_tiles_y());
186
187 TestPicturePile::PictureInfo& picture_info =
188 pile_->picture_map().find(TestPicturePile::PictureMapKey(0, 0))->second;
189 // We should have a picture.
190 EXPECT_TRUE(!!picture_info.GetPicture());
191 gfx::Rect picture_rect = gfx::ScaleToEnclosedRect(
192 picture_info.GetPicture()->LayerRect(), min_scale_);
193
194 // The the picture should be large enough that scaling it never makes a rect
195 // smaller than 1 px wide or tall.
196 EXPECT_FALSE(picture_rect.IsEmpty()) << "Picture rect " <<
197 picture_rect.ToString();
198}
199
200TEST_F(PicturePileTest, LargeInvalidateInflated) {
201 // Invalidate something inside a tile.
202 Region invalidate_rect(gfx::Rect(50, 50, 100, 100));
203 UpdateAndExpandInvalidation(&invalidate_rect, tiling_size(), tiling_rect());
204 EXPECT_EQ(gfx::Rect(50, 50, 100, 100).ToString(), invalidate_rect.ToString());
205
206 EXPECT_EQ(1, pile_->tiling().num_tiles_x());
207 EXPECT_EQ(1, pile_->tiling().num_tiles_y());
208
209 TestPicturePile::PictureInfo& picture_info =
210 pile_->picture_map().find(TestPicturePile::PictureMapKey(0, 0))->second;
211 EXPECT_TRUE(!!picture_info.GetPicture());
212
213 int expected_inflation = pile_->buffer_pixels();
214
215 const Picture* base_picture = picture_info.GetPicture();
216 gfx::Rect base_picture_rect(pile_->tiling_size());
217 base_picture_rect.Inset(-expected_inflation, -expected_inflation);
218 EXPECT_EQ(base_picture_rect.ToString(),
219 base_picture->LayerRect().ToString());
220}
221
222TEST_F(PicturePileTest, InvalidateOnTileBoundaryInflated) {
223 gfx::Size new_tiling_size =
224 gfx::ToCeiledSize(gfx::ScaleSize(pile_->tiling_size(), 2.f));
225 // This creates initial pictures.
226 SetTilingSize(new_tiling_size);
227
228 // Due to border pixels, we should have 3 tiles.
229 EXPECT_EQ(3, pile_->tiling().num_tiles_x());
230 EXPECT_EQ(3, pile_->tiling().num_tiles_y());
231
232 // We should have 1/.125 - 1 = 7 border pixels.
233 EXPECT_EQ(7, pile_->buffer_pixels());
234 EXPECT_EQ(7, pile_->tiling().border_texels());
235
236 // Invalidate everything to have a non zero invalidation frequency.
237 UpdateWholePile();
238
239 // Invalidate something just over a tile boundary by a single pixel.
240 // This will invalidate the tile (1, 1), as well as 1 row of pixels in (1, 0).
241 Region invalidate_rect(
242 gfx::Rect(pile_->tiling().TileBoundsWithBorder(0, 0).right(),
243 pile_->tiling().TileBoundsWithBorder(0, 0).bottom() - 1,
244 50,
245 50));
246 Region expected_invalidation = invalidate_rect;
247 UpdateAndExpandInvalidation(&invalidate_rect, tiling_size(), tiling_rect());
248 EXPECT_EQ(expected_invalidation.ToString(), invalidate_rect.ToString());
249
250 for (int i = 0; i < pile_->tiling().num_tiles_x(); ++i) {
251 for (int j = 0; j < pile_->tiling().num_tiles_y(); ++j) {
252 TestPicturePile::PictureInfo& picture_info =
253 pile_->picture_map()
254 .find(TestPicturePile::PictureMapKey(i, j))
255 ->second;
256
257 // Expect (1, 1) and (1, 0) to be invalidated once more
258 // than the rest of the tiles.
259 if (i == 1 && (j == 0 || j == 1)) {
260 EXPECT_FLOAT_EQ(
261 2.0f / TestPicturePile::PictureInfo::INVALIDATION_FRAMES_TRACKED,
262 picture_info.GetInvalidationFrequencyForTesting());
263 } else {
264 EXPECT_FLOAT_EQ(
265 1.0f / TestPicturePile::PictureInfo::INVALIDATION_FRAMES_TRACKED,
266 picture_info.GetInvalidationFrequencyForTesting());
267 }
268 }
269 }
270}
271
James Robinsone2ac7e82014-10-15 13:21:59 -0700272TEST_F(PicturePileTest, InvalidateOnFullLayer) {
273 UpdateWholePile();
274
275 // Everything was invalidated once so far.
276 for (auto& it : pile_->picture_map()) {
277 EXPECT_FLOAT_EQ(
278 1.0f / TestPicturePile::PictureInfo::INVALIDATION_FRAMES_TRACKED,
279 it.second.GetInvalidationFrequencyForTesting());
280 }
281
282 // Invalidate everything,
283 Region invalidation = tiling_rect();
284 UpdateAndExpandInvalidation(&invalidation, tiling_size(), tiling_rect());
285
286 // Everything was invalidated again.
287 for (auto& it : pile_->picture_map()) {
288 EXPECT_FLOAT_EQ(
289 2.0f / TestPicturePile::PictureInfo::INVALIDATION_FRAMES_TRACKED,
290 it.second.GetInvalidationFrequencyForTesting());
291 }
292}
293
James Robinson646469d2014-10-03 15:33:28 -0700294TEST_F(PicturePileTest, StopRecordingOffscreenInvalidations) {
295 gfx::Size new_tiling_size =
296 gfx::ToCeiledSize(gfx::ScaleSize(pile_->tiling_size(), 4.f));
297 SetTilingSize(new_tiling_size);
298
299 gfx::Rect viewport(tiling_size().width(), 1);
300
301 // Update the whole pile until the invalidation frequency is high.
302 for (int frame = 0; frame < 33; ++frame) {
303 UpdateWholePile();
304 }
305
306 // Make sure we have a high invalidation frequency.
307 for (int i = 0; i < pile_->tiling().num_tiles_x(); ++i) {
308 for (int j = 0; j < pile_->tiling().num_tiles_y(); ++j) {
309 TestPicturePile::PictureInfo& picture_info =
310 pile_->picture_map()
311 .find(TestPicturePile::PictureMapKey(i, j))
312 ->second;
313 EXPECT_FLOAT_EQ(1.0f, picture_info.GetInvalidationFrequencyForTesting())
314 << "i " << i << " j " << j;
315 }
316 }
317
318 // Update once more with a small viewport.
319 Region invalidation(tiling_rect());
320 UpdateAndExpandInvalidation(&invalidation, tiling_size(), viewport);
321 EXPECT_EQ(tiling_rect().ToString(), invalidation.ToString());
322
323 for (int i = 0; i < pile_->tiling().num_tiles_x(); ++i) {
324 for (int j = 0; j < pile_->tiling().num_tiles_y(); ++j) {
325 TestPicturePile::PictureInfo& picture_info =
326 pile_->picture_map()
327 .find(TestPicturePile::PictureMapKey(i, j))
328 ->second;
329 EXPECT_FLOAT_EQ(1.0f, picture_info.GetInvalidationFrequencyForTesting());
330
331 // If the y far enough away we expect to find no picture (no re-recording
332 // happened). For close y, the picture should change.
333 if (j >= 2)
334 EXPECT_FALSE(picture_info.GetPicture()) << "i " << i << " j " << j;
335 else
336 EXPECT_TRUE(picture_info.GetPicture()) << "i " << i << " j " << j;
337 }
338 }
339
340 // Update a partial tile that doesn't get recorded. We should expand the
341 // invalidation to the entire tiles that overlap it.
342 Region small_invalidation =
343 gfx::Rect(pile_->tiling().TileBounds(3, 4).x(),
344 pile_->tiling().TileBounds(3, 4).y() + 10,
345 1,
346 1);
347 UpdateAndExpandInvalidation(&small_invalidation, tiling_size(), viewport);
348 EXPECT_TRUE(small_invalidation.Contains(gfx::UnionRects(
349 pile_->tiling().TileBounds(2, 4), pile_->tiling().TileBounds(3, 4))))
350 << small_invalidation.ToString();
351
352 // Now update with no invalidation and full viewport
353 Region empty_invalidation;
354 UpdateAndExpandInvalidation(
355 &empty_invalidation, tiling_size(), tiling_rect());
356 EXPECT_EQ(Region().ToString(), empty_invalidation.ToString());
357
358 for (int i = 0; i < pile_->tiling().num_tiles_x(); ++i) {
359 for (int j = 0; j < pile_->tiling().num_tiles_y(); ++j) {
360 TestPicturePile::PictureInfo& picture_info =
361 pile_->picture_map()
362 .find(TestPicturePile::PictureMapKey(i, j))
363 ->second;
364 // Expect the invalidation frequency to be less than 1, since we just
365 // updated with no invalidations.
366 EXPECT_LT(picture_info.GetInvalidationFrequencyForTesting(), 1.f);
367
368 // We expect that there are pictures everywhere now.
369 EXPECT_TRUE(picture_info.GetPicture()) << "i " << i << " j " << j;
370 }
371 }
372}
373
374TEST_F(PicturePileTest, ClearingInvalidatesRecordedRect) {
375 gfx::Rect rect(0, 0, 5, 5);
376 EXPECT_TRUE(pile_->CanRasterLayerRect(rect));
377 EXPECT_TRUE(pile_->CanRasterSlowTileCheck(rect));
378
379 pile_->Clear();
380
381 // Make sure both the cache-aware check (using recorded region) and the normal
382 // check are both false after clearing.
383 EXPECT_FALSE(pile_->CanRasterLayerRect(rect));
384 EXPECT_FALSE(pile_->CanRasterSlowTileCheck(rect));
385}
386
387TEST_F(PicturePileTest, FrequentInvalidationCanRaster) {
388 // This test makes sure that if part of the page is frequently invalidated
389 // and doesn't get re-recorded, then CanRaster is not true for any
390 // tiles touching it, but is true for adjacent tiles, even if it
391 // overlaps on borders (edge case).
392 gfx::Size new_tiling_size =
393 gfx::ToCeiledSize(gfx::ScaleSize(pile_->tiling_size(), 4.f));
394 SetTilingSize(new_tiling_size);
395
396 gfx::Rect tile01_borders = pile_->tiling().TileBoundsWithBorder(0, 1);
397 gfx::Rect tile02_borders = pile_->tiling().TileBoundsWithBorder(0, 2);
398 gfx::Rect tile01_noborders = pile_->tiling().TileBounds(0, 1);
399 gfx::Rect tile02_noborders = pile_->tiling().TileBounds(0, 2);
400
401 // Sanity check these two tiles are overlapping with borders, since this is
402 // what the test is trying to repro.
403 EXPECT_TRUE(tile01_borders.Intersects(tile02_borders));
404 EXPECT_FALSE(tile01_noborders.Intersects(tile02_noborders));
405 UpdateWholePile();
406 EXPECT_TRUE(pile_->CanRasterLayerRect(tile01_noborders));
407 EXPECT_TRUE(pile_->CanRasterSlowTileCheck(tile01_noborders));
408 EXPECT_TRUE(pile_->CanRasterLayerRect(tile02_noborders));
409 EXPECT_TRUE(pile_->CanRasterSlowTileCheck(tile02_noborders));
410 // Sanity check that an initial paint goes down the fast path of having
411 // a valid recorded viewport.
412 EXPECT_TRUE(!pile_->recorded_viewport().IsEmpty());
413
414 // Update the whole layer until the invalidation frequency is high.
415 for (int frame = 0; frame < 33; ++frame) {
416 UpdateWholePile();
417 }
418
419 // Update once more with a small viewport.
420 gfx::Rect viewport(tiling_size().width(), 1);
421 Region invalidation(tiling_rect());
422 UpdateAndExpandInvalidation(&invalidation, tiling_size(), viewport);
423 EXPECT_EQ(tiling_rect().ToString(), invalidation.ToString());
424
425 // Sanity check some pictures exist and others don't.
426 EXPECT_TRUE(pile_->picture_map()
427 .find(TestPicturePile::PictureMapKey(0, 1))
428 ->second.GetPicture());
429 EXPECT_FALSE(pile_->picture_map()
430 .find(TestPicturePile::PictureMapKey(0, 2))
431 ->second.GetPicture());
432
433 EXPECT_TRUE(pile_->CanRasterLayerRect(tile01_noborders));
434 EXPECT_TRUE(pile_->CanRasterSlowTileCheck(tile01_noborders));
435 EXPECT_FALSE(pile_->CanRasterLayerRect(tile02_noborders));
436 EXPECT_FALSE(pile_->CanRasterSlowTileCheck(tile02_noborders));
437}
438
439TEST_F(PicturePileTest, NoInvalidationValidViewport) {
440 // This test validates that the recorded_viewport cache of full tiles
441 // is still valid for some use cases. If it's not, it's a performance
442 // issue because CanRaster checks will go down the slow path.
443 EXPECT_TRUE(!pile_->recorded_viewport().IsEmpty());
444
445 // No invalidation, same viewport.
446 Region invalidation;
447 UpdateAndExpandInvalidation(&invalidation, tiling_size(), tiling_rect());
448 EXPECT_TRUE(!pile_->recorded_viewport().IsEmpty());
449 EXPECT_EQ(Region().ToString(), invalidation.ToString());
450
451 // Partial invalidation, same viewport.
452 invalidation = gfx::Rect(0, 0, 1, 1);
453 UpdateAndExpandInvalidation(&invalidation, tiling_size(), tiling_rect());
454 EXPECT_TRUE(!pile_->recorded_viewport().IsEmpty());
455 EXPECT_EQ(gfx::Rect(0, 0, 1, 1).ToString(), invalidation.ToString());
456
457 // No invalidation, changing viewport.
458 invalidation = Region();
459 UpdateAndExpandInvalidation(
460 &invalidation, tiling_size(), gfx::Rect(5, 5, 5, 5));
461 EXPECT_TRUE(!pile_->recorded_viewport().IsEmpty());
462 EXPECT_EQ(Region().ToString(), invalidation.ToString());
463}
464
James Robinsone2ac7e82014-10-15 13:21:59 -0700465TEST_F(PicturePileTest, BigFullLayerInvalidation) {
466 gfx::Size huge_layer_size(100000000, 100000000);
467 gfx::Rect viewport(300000, 400000, 5000, 6000);
468
469 // Resize the pile.
470 Region invalidation;
471 UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
472
473 // Invalidating a huge layer should be fast.
474 base::TimeTicks start = base::TimeTicks::Now();
475 invalidation = gfx::Rect(huge_layer_size);
476 UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
477 base::TimeTicks end = base::TimeTicks::Now();
478 base::TimeDelta length = end - start;
479 // This is verrrry generous to avoid flake.
480 EXPECT_LT(length.InSeconds(), 5);
481}
482
483TEST_F(PicturePileTest, BigFullLayerInvalidationWithResizeGrow) {
484 gfx::Size huge_layer_size(100000000, 100000000);
485 gfx::Rect viewport(300000, 400000, 5000, 6000);
486
487 // Resize the pile.
488 Region invalidation;
489 UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
490
491 // Resize the pile even larger, while invalidating everything in the old size.
492 // Invalidating the whole thing should be fast.
493 base::TimeTicks start = base::TimeTicks::Now();
494 gfx::Size bigger_layer_size(huge_layer_size.width() * 2,
495 huge_layer_size.height() * 2);
496 invalidation = gfx::Rect(huge_layer_size);
497 UpdateAndExpandInvalidation(&invalidation, bigger_layer_size, viewport);
498 base::TimeTicks end = base::TimeTicks::Now();
499 base::TimeDelta length = end - start;
500 // This is verrrry generous to avoid flake.
501 EXPECT_LT(length.InSeconds(), 5);
502}
503
504TEST_F(PicturePileTest, BigFullLayerInvalidationWithResizeShrink) {
505 gfx::Size huge_layer_size(100000000, 100000000);
506 gfx::Rect viewport(300000, 400000, 5000, 6000);
507
508 // Resize the pile.
509 Region invalidation;
510 UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
511
512 // Resize the pile smaller, while invalidating everything in the new size.
513 // Invalidating the whole thing should be fast.
514 base::TimeTicks start = base::TimeTicks::Now();
515 gfx::Size smaller_layer_size(huge_layer_size.width() - 1000,
516 huge_layer_size.height() - 1000);
517 invalidation = gfx::Rect(smaller_layer_size);
518 UpdateAndExpandInvalidation(&invalidation, smaller_layer_size, viewport);
519 base::TimeTicks end = base::TimeTicks::Now();
520 base::TimeDelta length = end - start;
521 // This is verrrry generous to avoid flake.
522 EXPECT_LT(length.InSeconds(), 5);
523}
524
James Robinson646469d2014-10-03 15:33:28 -0700525TEST_F(PicturePileTest, InvalidationOutsideRecordingRect) {
526 gfx::Size huge_layer_size(10000000, 20000000);
527 gfx::Rect viewport(300000, 400000, 5000, 6000);
528
529 // Resize the pile and set up the interest rect.
530 Region invalidation;
531 UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
532
533 // Invalidation inside the recording rect does not need to be expanded.
534 invalidation = viewport;
535 UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
536 EXPECT_EQ(viewport.ToString(), invalidation.ToString());
537
538 // Invalidation outside the recording rect should expand to the tiles it
539 // covers.
540 gfx::Rect recorded_over_tiles =
541 pile_->tiling().ExpandRectToTileBounds(pile_->recorded_viewport());
542 gfx::Rect invalidation_outside(
543 recorded_over_tiles.right(), recorded_over_tiles.y(), 30, 30);
544 invalidation = invalidation_outside;
545 UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
546 gfx::Rect expanded_recorded_viewport =
547 pile_->tiling().ExpandRectToTileBounds(pile_->recorded_viewport());
548 Region expected_invalidation =
549 pile_->tiling().ExpandRectToTileBounds(invalidation_outside);
550 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
551}
552
553enum Corner {
554 TOP_LEFT,
555 TOP_RIGHT,
556 BOTTOM_LEFT,
557 BOTTOM_RIGHT,
558};
559
560class PicturePileResizeCornerTest : public PicturePileTestBase,
561 public testing::TestWithParam<Corner> {
562 protected:
James Robinsonbaf71d32014-10-08 13:00:20 -0700563 virtual void SetUp() override { InitializeData(); }
James Robinson646469d2014-10-03 15:33:28 -0700564
565 static gfx::Rect CornerSinglePixelRect(Corner corner, const gfx::Size& s) {
566 switch (corner) {
567 case TOP_LEFT:
568 return gfx::Rect(0, 0, 1, 1);
569 case TOP_RIGHT:
570 return gfx::Rect(s.width() - 1, 0, 1, 1);
571 case BOTTOM_LEFT:
572 return gfx::Rect(0, s.height() - 1, 1, 1);
573 case BOTTOM_RIGHT:
574 return gfx::Rect(s.width() - 1, s.height() - 1, 1, 1);
575 }
576 NOTREACHED();
577 return gfx::Rect();
578 }
579};
580
581TEST_P(PicturePileResizeCornerTest, ResizePileOutsideInterestRect) {
582 Corner corner = GetParam();
583
584 // This size chosen to be larger than the interest rect size, which is
585 // at least kPixelDistanceToRecord * 2 in each dimension.
586 int tile_size = 100000;
587 // The small number subtracted keeps the last tile in each axis larger than
588 // the interest rect also.
589 int offset = -100;
590 gfx::Size base_tiling_size(6 * tile_size + offset, 6 * tile_size + offset);
591 gfx::Size grow_down_tiling_size(6 * tile_size + offset,
592 8 * tile_size + offset);
593 gfx::Size grow_right_tiling_size(8 * tile_size + offset,
594 6 * tile_size + offset);
595 gfx::Size grow_both_tiling_size(8 * tile_size + offset,
596 8 * tile_size + offset);
597
598 Region invalidation;
599 Region expected_invalidation;
600
601 pile_->tiling().SetMaxTextureSize(gfx::Size(tile_size, tile_size));
602 SetTilingSize(base_tiling_size);
603
604 // We should have a recording for every tile.
605 EXPECT_EQ(6, pile_->tiling().num_tiles_x());
606 EXPECT_EQ(6, pile_->tiling().num_tiles_y());
607 for (int i = 0; i < pile_->tiling().num_tiles_x(); ++i) {
608 for (int j = 0; j < pile_->tiling().num_tiles_y(); ++j) {
609 TestPicturePile::PictureMapKey key(i, j);
610 TestPicturePile::PictureMap& map = pile_->picture_map();
611 TestPicturePile::PictureMap::iterator it = map.find(key);
612 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
613 }
614 }
615
616 UpdateAndExpandInvalidation(
617 &invalidation,
618 grow_down_tiling_size,
619 CornerSinglePixelRect(corner, grow_down_tiling_size));
620
621 // We should have lost the recordings in the bottom row.
622 EXPECT_EQ(6, pile_->tiling().num_tiles_x());
623 EXPECT_EQ(8, pile_->tiling().num_tiles_y());
624 for (int i = 0; i < 6; ++i) {
625 for (int j = 0; j < 6; ++j) {
626 TestPicturePile::PictureMapKey key(i, j);
627 TestPicturePile::PictureMap& map = pile_->picture_map();
628 TestPicturePile::PictureMap::iterator it = map.find(key);
629 EXPECT_EQ(j < 5, it != map.end() && it->second.GetPicture());
630 }
631 }
632
633 // We invalidated all new pixels in the recording.
634 expected_invalidation = SubtractRegions(gfx::Rect(grow_down_tiling_size),
635 gfx::Rect(base_tiling_size));
636 // But the new pixels don't cover the whole bottom row.
637 gfx::Rect bottom_row = gfx::UnionRects(pile_->tiling().TileBounds(0, 5),
638 pile_->tiling().TileBounds(5, 5));
639 EXPECT_FALSE(expected_invalidation.Contains(bottom_row));
640 // We invalidated the entire old bottom row.
641 expected_invalidation.Union(bottom_row);
642 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
643 invalidation.Clear();
644
645 UpdateWholePile();
646 UpdateAndExpandInvalidation(&invalidation,
647 base_tiling_size,
648 CornerSinglePixelRect(corner, base_tiling_size));
649
650 // We should have lost the recordings that are now outside the tiling only.
651 EXPECT_EQ(6, pile_->tiling().num_tiles_x());
652 EXPECT_EQ(6, pile_->tiling().num_tiles_y());
653 for (int i = 0; i < pile_->tiling().num_tiles_x(); ++i) {
654 for (int j = 0; j < pile_->tiling().num_tiles_y(); ++j) {
655 TestPicturePile::PictureMapKey key(i, j);
656 TestPicturePile::PictureMap& map = pile_->picture_map();
657 TestPicturePile::PictureMap::iterator it = map.find(key);
658 EXPECT_EQ(j < 6, it != map.end() && it->second.GetPicture());
659 }
660 }
661
662 // No invalidation when shrinking.
663 expected_invalidation.Clear();
664 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
665 invalidation.Clear();
666
667 UpdateWholePile();
668 UpdateAndExpandInvalidation(
669 &invalidation,
670 grow_right_tiling_size,
671 CornerSinglePixelRect(corner, grow_right_tiling_size));
672
673 // We should have lost the recordings in the right column.
674 EXPECT_EQ(8, pile_->tiling().num_tiles_x());
675 EXPECT_EQ(6, pile_->tiling().num_tiles_y());
676 for (int i = 0; i < 6; ++i) {
677 for (int j = 0; j < 6; ++j) {
678 TestPicturePile::PictureMapKey key(i, j);
679 TestPicturePile::PictureMap& map = pile_->picture_map();
680 TestPicturePile::PictureMap::iterator it = map.find(key);
681 EXPECT_EQ(i < 5, it != map.end() && it->second.GetPicture());
682 }
683 }
684
685 // We invalidated all new pixels in the recording.
686 expected_invalidation = SubtractRegions(gfx::Rect(grow_right_tiling_size),
687 gfx::Rect(base_tiling_size));
688 // But the new pixels don't cover the whole right_column.
689 gfx::Rect right_column = gfx::UnionRects(pile_->tiling().TileBounds(5, 0),
690 pile_->tiling().TileBounds(5, 5));
691 EXPECT_FALSE(expected_invalidation.Contains(right_column));
692 // We invalidated the entire old right column.
693 expected_invalidation.Union(right_column);
694 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
695 invalidation.Clear();
696
697 UpdateWholePile();
698 UpdateAndExpandInvalidation(&invalidation,
699 base_tiling_size,
700 CornerSinglePixelRect(corner, base_tiling_size));
701
702 // We should have lost the recordings that are now outside the tiling only.
703 EXPECT_EQ(6, pile_->tiling().num_tiles_x());
704 EXPECT_EQ(6, pile_->tiling().num_tiles_y());
705 for (int i = 0; i < pile_->tiling().num_tiles_x(); ++i) {
706 for (int j = 0; j < pile_->tiling().num_tiles_y(); ++j) {
707 TestPicturePile::PictureMapKey key(i, j);
708 TestPicturePile::PictureMap& map = pile_->picture_map();
709 TestPicturePile::PictureMap::iterator it = map.find(key);
710 EXPECT_EQ(i < 6, it != map.end() && it->second.GetPicture());
711 }
712 }
713
714 // No invalidation when shrinking.
715 expected_invalidation.Clear();
716 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
717 invalidation.Clear();
718
719 UpdateWholePile();
720 UpdateAndExpandInvalidation(
721 &invalidation,
722 grow_both_tiling_size,
723 CornerSinglePixelRect(corner, grow_both_tiling_size));
724
725 // We should have lost the recordings in the right column and bottom row.
726 EXPECT_EQ(8, pile_->tiling().num_tiles_x());
727 EXPECT_EQ(8, pile_->tiling().num_tiles_y());
728 for (int i = 0; i < 6; ++i) {
729 for (int j = 0; j < 6; ++j) {
730 TestPicturePile::PictureMapKey key(i, j);
731 TestPicturePile::PictureMap& map = pile_->picture_map();
732 TestPicturePile::PictureMap::iterator it = map.find(key);
733 EXPECT_EQ(i < 5 && j < 5, it != map.end() && it->second.GetPicture());
734 }
735 }
736
737 // We invalidated all new pixels in the recording.
738 expected_invalidation = SubtractRegions(gfx::Rect(grow_both_tiling_size),
739 gfx::Rect(base_tiling_size));
740 // But the new pixels don't cover the whole right_column.
741 Region right_column_and_bottom_row =
742 UnionRegions(gfx::UnionRects(pile_->tiling().TileBounds(5, 0),
743 pile_->tiling().TileBounds(5, 5)),
744 gfx::UnionRects(pile_->tiling().TileBounds(0, 5),
745 pile_->tiling().TileBounds(5, 5)));
746 EXPECT_FALSE(expected_invalidation.Contains(right_column_and_bottom_row));
747 // We invalidated the entire old right column and the old bottom row.
748 expected_invalidation.Union(right_column_and_bottom_row);
749 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
750 invalidation.Clear();
751
752 UpdateWholePile();
753 UpdateAndExpandInvalidation(&invalidation, base_tiling_size, gfx::Rect());
754
755 // We should have lost the recordings that are now outside the tiling only.
756 EXPECT_EQ(6, pile_->tiling().num_tiles_x());
757 EXPECT_EQ(6, pile_->tiling().num_tiles_y());
758 for (int i = 0; i < pile_->tiling().num_tiles_x(); ++i) {
759 for (int j = 0; j < pile_->tiling().num_tiles_y(); ++j) {
760 TestPicturePile::PictureMapKey key(i, j);
761 TestPicturePile::PictureMap& map = pile_->picture_map();
762 TestPicturePile::PictureMap::iterator it = map.find(key);
763 EXPECT_EQ(i < 6 && j < 6, it != map.end() && it->second.GetPicture());
764 }
765 }
766
767 // No invalidation when shrinking.
768 expected_invalidation.Clear();
769 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
770 invalidation.Clear();
771}
772
773TEST_P(PicturePileResizeCornerTest, SmallResizePileOutsideInterestRect) {
774 Corner corner = GetParam();
775
776 // This size chosen to be larger than the interest rect size, which is
777 // at least kPixelDistanceToRecord * 2 in each dimension.
778 int tile_size = 100000;
779 // The small number subtracted keeps the last tile in each axis larger than
780 // the interest rect also.
781 int offset = -100;
782 gfx::Size base_tiling_size(6 * tile_size + offset, 6 * tile_size + offset);
783 gfx::Size grow_down_tiling_size(6 * tile_size + offset,
784 6 * tile_size + offset + 5);
785 gfx::Size grow_right_tiling_size(6 * tile_size + offset + 5,
786 6 * tile_size + offset);
787 gfx::Size grow_both_tiling_size(6 * tile_size + offset + 5,
788 6 * tile_size + offset + 5);
789
790 Region invalidation;
791 Region expected_invalidation;
792
793 pile_->tiling().SetMaxTextureSize(gfx::Size(tile_size, tile_size));
794 SetTilingSize(base_tiling_size);
795
796 // We should have a recording for every tile.
797 EXPECT_EQ(6, pile_->tiling().num_tiles_x());
798 EXPECT_EQ(6, pile_->tiling().num_tiles_y());
799 for (int i = 0; i < pile_->tiling().num_tiles_x(); ++i) {
800 for (int j = 0; j < pile_->tiling().num_tiles_y(); ++j) {
801 TestPicturePile::PictureMapKey key(i, j);
802 TestPicturePile::PictureMap& map = pile_->picture_map();
803 TestPicturePile::PictureMap::iterator it = map.find(key);
804 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
805 }
806 }
807
808 UpdateAndExpandInvalidation(
809 &invalidation,
810 grow_down_tiling_size,
811 CornerSinglePixelRect(corner, grow_down_tiling_size));
812
813 // We should have lost the recordings in the bottom row that do not intersect
814 // the interest rect.
815 EXPECT_EQ(6, pile_->tiling().num_tiles_x());
816 EXPECT_EQ(6, pile_->tiling().num_tiles_y());
817 for (int i = 0; i < pile_->tiling().num_tiles_x(); ++i) {
818 for (int j = 0; j < pile_->tiling().num_tiles_y(); ++j) {
819 TestPicturePile::PictureMapKey key(i, j);
820 TestPicturePile::PictureMap& map = pile_->picture_map();
821 TestPicturePile::PictureMap::iterator it = map.find(key);
822 bool expect_tile;
823 switch (corner) {
824 case TOP_LEFT:
825 case TOP_RIGHT:
826 expect_tile = j < 5;
827 break;
828 case BOTTOM_LEFT:
829 // The interest rect in the bottom left tile means we'll record it.
830 expect_tile = j < 5 || (j == 5 && i == 0);
831 break;
832 case BOTTOM_RIGHT:
833 // The interest rect in the bottom right tile means we'll record it.
834 expect_tile = j < 5 || (j == 5 && i == 5);
835 break;
836 }
837 EXPECT_EQ(expect_tile, it != map.end() && it->second.GetPicture());
838 }
839 }
840
841 // We invalidated the bottom row outside the new interest rect. The tile that
842 // insects the interest rect in invalidated only on its new pixels.
843 switch (corner) {
844 case TOP_LEFT:
845 case TOP_RIGHT:
846 expected_invalidation = gfx::UnionRects(pile_->tiling().TileBounds(0, 5),
847 pile_->tiling().TileBounds(5, 5));
848 break;
849 case BOTTOM_LEFT:
850 expected_invalidation = gfx::UnionRects(pile_->tiling().TileBounds(1, 5),
851 pile_->tiling().TileBounds(5, 5));
852 expected_invalidation.Union(SubtractRects(
853 pile_->tiling().TileBounds(0, 5), gfx::Rect(base_tiling_size)));
854 break;
855 case BOTTOM_RIGHT:
856 expected_invalidation = gfx::UnionRects(pile_->tiling().TileBounds(0, 5),
857 pile_->tiling().TileBounds(4, 5));
858 expected_invalidation.Union(SubtractRects(
859 pile_->tiling().TileBounds(5, 5), gfx::Rect(base_tiling_size)));
860 break;
861 }
862 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
863 invalidation.Clear();
864
865 UpdateWholePile();
866 UpdateAndExpandInvalidation(&invalidation,
867 base_tiling_size,
868 CornerSinglePixelRect(corner, base_tiling_size));
869
870 // We should have lost nothing.
871 EXPECT_EQ(6, pile_->tiling().num_tiles_x());
872 EXPECT_EQ(6, pile_->tiling().num_tiles_y());
873 for (int i = 0; i < pile_->tiling().num_tiles_x(); ++i) {
874 for (int j = 0; j < pile_->tiling().num_tiles_y(); ++j) {
875 TestPicturePile::PictureMapKey key(i, j);
876 TestPicturePile::PictureMap& map = pile_->picture_map();
877 TestPicturePile::PictureMap::iterator it = map.find(key);
878 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
879 }
880 }
881
882 // We invalidated nothing.
883 expected_invalidation.Clear();
884 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
885 invalidation.Clear();
886
887 UpdateWholePile();
888 UpdateAndExpandInvalidation(
889 &invalidation,
890 grow_right_tiling_size,
891 CornerSinglePixelRect(corner, grow_right_tiling_size));
892
893 // We should have lost the recordings in the right column.
894 EXPECT_EQ(6, pile_->tiling().num_tiles_x());
895 EXPECT_EQ(6, pile_->tiling().num_tiles_y());
896 for (int i = 0; i < pile_->tiling().num_tiles_x(); ++i) {
897 for (int j = 0; j < pile_->tiling().num_tiles_y(); ++j) {
898 TestPicturePile::PictureMapKey key(i, j);
899 TestPicturePile::PictureMap& map = pile_->picture_map();
900 TestPicturePile::PictureMap::iterator it = map.find(key);
901 bool expect_tile;
902 switch (corner) {
903 case TOP_LEFT:
904 case BOTTOM_LEFT:
905 expect_tile = i < 5;
906 break;
907 case TOP_RIGHT:
908 // The interest rect in the top right tile means we'll record it.
909 expect_tile = i < 5 || (j == 0 && i == 5);
910 break;
911 case BOTTOM_RIGHT:
912 // The interest rect in the bottom right tile means we'll record it.
913 expect_tile = i < 5 || (j == 5 && i == 5);
914 break;
915 }
916 EXPECT_EQ(expect_tile, it != map.end() && it->second.GetPicture());
917 }
918 }
919
920 // We invalidated the right column outside the new interest rect. The tile
921 // that insects the interest rect in invalidated only on its new pixels.
922 switch (corner) {
923 case TOP_LEFT:
924 case BOTTOM_LEFT:
925 expected_invalidation = gfx::UnionRects(pile_->tiling().TileBounds(5, 0),
926 pile_->tiling().TileBounds(5, 5));
927 break;
928 case TOP_RIGHT:
929 expected_invalidation = gfx::UnionRects(pile_->tiling().TileBounds(5, 1),
930 pile_->tiling().TileBounds(5, 5));
931 expected_invalidation.Union(SubtractRects(
932 pile_->tiling().TileBounds(5, 0), gfx::Rect(base_tiling_size)));
933 break;
934 case BOTTOM_RIGHT:
935 expected_invalidation = gfx::UnionRects(pile_->tiling().TileBounds(5, 0),
936 pile_->tiling().TileBounds(5, 4));
937 expected_invalidation.Union(SubtractRects(
938 pile_->tiling().TileBounds(5, 5), gfx::Rect(base_tiling_size)));
939 break;
940 }
941 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
942 invalidation.Clear();
943
944 UpdateWholePile();
945 UpdateAndExpandInvalidation(&invalidation,
946 base_tiling_size,
947 CornerSinglePixelRect(corner, base_tiling_size));
948
949 // We should have lost nothing.
950 EXPECT_EQ(6, pile_->tiling().num_tiles_x());
951 EXPECT_EQ(6, pile_->tiling().num_tiles_y());
952 for (int i = 0; i < pile_->tiling().num_tiles_x(); ++i) {
953 for (int j = 0; j < pile_->tiling().num_tiles_y(); ++j) {
954 TestPicturePile::PictureMapKey key(i, j);
955 TestPicturePile::PictureMap& map = pile_->picture_map();
956 TestPicturePile::PictureMap::iterator it = map.find(key);
957 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
958 }
959 }
960
961 // We invalidated nothing.
962 expected_invalidation.Clear();
963 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
964 invalidation.Clear();
965
966 UpdateWholePile();
967 UpdateAndExpandInvalidation(
968 &invalidation,
969 grow_both_tiling_size,
970 CornerSinglePixelRect(corner, grow_both_tiling_size));
971
972 // We should have lost the recordings in the right column and bottom row. The
973 // tile that insects the interest rect in invalidated only on its new pixels.
974 EXPECT_EQ(6, pile_->tiling().num_tiles_x());
975 EXPECT_EQ(6, pile_->tiling().num_tiles_y());
976 for (int i = 0; i < pile_->tiling().num_tiles_x(); ++i) {
977 for (int j = 0; j < pile_->tiling().num_tiles_y(); ++j) {
978 TestPicturePile::PictureMapKey key(i, j);
979 TestPicturePile::PictureMap& map = pile_->picture_map();
980 TestPicturePile::PictureMap::iterator it = map.find(key);
981 bool expect_tile;
982 switch (corner) {
983 case TOP_LEFT:
984 expect_tile = i < 5 && j < 5;
985 break;
986 case TOP_RIGHT:
987 // The interest rect in the top right tile means we'll record it.
988 expect_tile = (i < 5 && j < 5) || (j == 0 && i == 5);
989 break;
990 case BOTTOM_LEFT:
991 // The interest rect in the bottom left tile means we'll record it.
992 expect_tile = (i < 5 && j < 5) || (j == 5 && i == 0);
993 break;
994 case BOTTOM_RIGHT:
995 // The interest rect in the bottom right tile means we'll record it.
996 expect_tile = (i < 5 && j < 5) || (j == 5 && i == 5);
997 break;
998 }
999 EXPECT_EQ(expect_tile, it != map.end() && it->second.GetPicture())
1000 << i << "," << j;
1001 }
1002 }
1003
1004 // We invalidated the right column and the bottom row outside the new interest
1005 // rect. The tile that insects the interest rect in invalidated only on its
1006 // new pixels.
1007 switch (corner) {
1008 case TOP_LEFT:
1009 expected_invalidation = gfx::UnionRects(pile_->tiling().TileBounds(5, 0),
1010 pile_->tiling().TileBounds(5, 5));
1011 expected_invalidation.Union(gfx::UnionRects(
1012 pile_->tiling().TileBounds(0, 5), pile_->tiling().TileBounds(5, 5)));
1013 break;
1014 case TOP_RIGHT:
1015 expected_invalidation = gfx::UnionRects(pile_->tiling().TileBounds(5, 1),
1016 pile_->tiling().TileBounds(5, 5));
1017 expected_invalidation.Union(gfx::UnionRects(
1018 pile_->tiling().TileBounds(0, 5), pile_->tiling().TileBounds(5, 5)));
1019 expected_invalidation.Union(SubtractRects(
1020 pile_->tiling().TileBounds(5, 0), gfx::Rect(base_tiling_size)));
1021 break;
1022 case BOTTOM_LEFT:
1023 expected_invalidation = gfx::UnionRects(pile_->tiling().TileBounds(5, 0),
1024 pile_->tiling().TileBounds(5, 5));
1025 expected_invalidation.Union(gfx::UnionRects(
1026 pile_->tiling().TileBounds(1, 5), pile_->tiling().TileBounds(5, 5)));
1027 expected_invalidation.Union(SubtractRects(
1028 pile_->tiling().TileBounds(0, 5), gfx::Rect(base_tiling_size)));
1029 break;
1030 case BOTTOM_RIGHT:
1031 expected_invalidation = gfx::UnionRects(pile_->tiling().TileBounds(5, 0),
1032 pile_->tiling().TileBounds(5, 4));
1033 expected_invalidation.Union(gfx::UnionRects(
1034 pile_->tiling().TileBounds(0, 5), pile_->tiling().TileBounds(4, 5)));
1035 expected_invalidation.Union(SubtractRegions(
1036 pile_->tiling().TileBounds(5, 5), gfx::Rect(base_tiling_size)));
1037 break;
1038 }
1039 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1040 invalidation.Clear();
1041
1042 UpdateWholePile();
1043 UpdateAndExpandInvalidation(&invalidation,
1044 base_tiling_size,
1045 CornerSinglePixelRect(corner, base_tiling_size));
1046
1047 // We should have lost nothing.
1048 EXPECT_EQ(6, pile_->tiling().num_tiles_x());
1049 EXPECT_EQ(6, pile_->tiling().num_tiles_y());
1050 for (int i = 0; i < pile_->tiling().num_tiles_x(); ++i) {
1051 for (int j = 0; j < pile_->tiling().num_tiles_y(); ++j) {
1052 TestPicturePile::PictureMapKey key(i, j);
1053 TestPicturePile::PictureMap& map = pile_->picture_map();
1054 TestPicturePile::PictureMap::iterator it = map.find(key);
1055 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1056 }
1057 }
1058
1059 // We invalidated nothing.
1060 expected_invalidation.Clear();
1061 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1062 invalidation.Clear();
1063}
1064
1065INSTANTIATE_TEST_CASE_P(
1066 PicturePileResizeCornerTests,
1067 PicturePileResizeCornerTest,
1068 ::testing::Values(TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT));
1069
1070TEST_F(PicturePileTest, ResizePileInsideInterestRect) {
1071 // This size chosen to be small enough that all the rects below fit inside the
1072 // the interest rect, so they are smaller than kPixelDistanceToRecord in each
1073 // dimension.
1074 int tile_size = 100;
1075 gfx::Size base_tiling_size(5 * tile_size, 5 * tile_size);
1076 gfx::Size grow_down_tiling_size(5 * tile_size, 7 * tile_size);
1077 gfx::Size grow_right_tiling_size(7 * tile_size, 5 * tile_size);
1078 gfx::Size grow_both_tiling_size(7 * tile_size, 7 * tile_size);
1079
1080 Region invalidation;
1081 Region expected_invalidation;
1082
1083 pile_->tiling().SetMaxTextureSize(gfx::Size(tile_size, tile_size));
1084 SetTilingSize(base_tiling_size);
1085
1086 // We should have a recording for every tile.
1087 EXPECT_EQ(6, pile_->tiling().num_tiles_x());
1088 EXPECT_EQ(6, pile_->tiling().num_tiles_y());
1089 for (int i = 0; i < pile_->tiling().num_tiles_x(); ++i) {
1090 for (int j = 0; j < pile_->tiling().num_tiles_y(); ++j) {
1091 TestPicturePile::PictureMapKey key(i, j);
1092 TestPicturePile::PictureMap& map = pile_->picture_map();
1093 TestPicturePile::PictureMap::iterator it = map.find(key);
1094 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1095 }
1096 }
1097
1098 UpdateAndExpandInvalidation(
1099 &invalidation, grow_down_tiling_size, gfx::Rect(1, 1));
1100
1101 // We should have a recording for every tile.
1102 EXPECT_EQ(6, pile_->tiling().num_tiles_x());
1103 EXPECT_EQ(8, pile_->tiling().num_tiles_y());
1104 for (int i = 0; i < pile_->tiling().num_tiles_x(); ++i) {
1105 for (int j = 0; j < pile_->tiling().num_tiles_y(); ++j) {
1106 TestPicturePile::PictureMapKey key(i, j);
1107 TestPicturePile::PictureMap& map = pile_->picture_map();
1108 TestPicturePile::PictureMap::iterator it = map.find(key);
1109 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1110 }
1111 }
1112
1113 // We invalidated the newly exposed pixels on the bottom row of tiles.
1114 expected_invalidation = SubtractRegions(gfx::Rect(grow_down_tiling_size),
1115 gfx::Rect(base_tiling_size));
1116 Region bottom_row_new_pixels =
1117 SubtractRegions(gfx::UnionRects(pile_->tiling().TileBounds(0, 5),
1118 pile_->tiling().TileBounds(5, 5)),
1119 gfx::Rect(base_tiling_size));
1120 EXPECT_TRUE(expected_invalidation.Contains(bottom_row_new_pixels));
1121 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1122 invalidation.Clear();
1123
1124 UpdateWholePile();
1125 UpdateAndExpandInvalidation(&invalidation, base_tiling_size, gfx::Rect(1, 1));
1126
1127 // We should have a recording for every tile.
1128 EXPECT_EQ(6, pile_->tiling().num_tiles_x());
1129 EXPECT_EQ(6, pile_->tiling().num_tiles_y());
1130 for (int i = 0; i < pile_->tiling().num_tiles_x(); ++i) {
1131 for (int j = 0; j < pile_->tiling().num_tiles_y(); ++j) {
1132 TestPicturePile::PictureMapKey key(i, j);
1133 TestPicturePile::PictureMap& map = pile_->picture_map();
1134 TestPicturePile::PictureMap::iterator it = map.find(key);
1135 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1136 }
1137 }
1138
1139 // No invalidation when shrinking.
1140 EXPECT_EQ(Region().ToString(), invalidation.ToString());
1141 invalidation.Clear();
1142
1143 UpdateWholePile();
1144 UpdateAndExpandInvalidation(
1145 &invalidation, grow_right_tiling_size, gfx::Rect(1, 1));
1146
1147 // We should have a recording for every tile.
1148 EXPECT_EQ(8, pile_->tiling().num_tiles_x());
1149 EXPECT_EQ(6, pile_->tiling().num_tiles_y());
1150 for (int i = 0; i < pile_->tiling().num_tiles_x(); ++i) {
1151 for (int j = 0; j < pile_->tiling().num_tiles_y(); ++j) {
1152 TestPicturePile::PictureMapKey key(i, j);
1153 TestPicturePile::PictureMap& map = pile_->picture_map();
1154 TestPicturePile::PictureMap::iterator it = map.find(key);
1155 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1156 }
1157 }
1158
1159 // We invalidated the newly exposed pixels on the right column of tiles.
1160 expected_invalidation = SubtractRegions(gfx::Rect(grow_right_tiling_size),
1161 gfx::Rect(base_tiling_size));
1162 Region right_column_new_pixels =
1163 SubtractRegions(gfx::UnionRects(pile_->tiling().TileBounds(5, 0),
1164 pile_->tiling().TileBounds(5, 5)),
1165 gfx::Rect(base_tiling_size));
1166 EXPECT_TRUE(expected_invalidation.Contains(right_column_new_pixels));
1167 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1168 invalidation.Clear();
1169
1170 UpdateWholePile();
1171 UpdateAndExpandInvalidation(&invalidation, base_tiling_size, gfx::Rect(1, 1));
1172
1173 // We should have lost the recordings that are now outside the tiling only.
1174 EXPECT_EQ(6, pile_->tiling().num_tiles_x());
1175 EXPECT_EQ(6, pile_->tiling().num_tiles_y());
1176 for (int i = 0; i < pile_->tiling().num_tiles_x(); ++i) {
1177 for (int j = 0; j < pile_->tiling().num_tiles_y(); ++j) {
1178 TestPicturePile::PictureMapKey key(i, j);
1179 TestPicturePile::PictureMap& map = pile_->picture_map();
1180 TestPicturePile::PictureMap::iterator it = map.find(key);
1181 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1182 }
1183 }
1184
1185 // No invalidation when shrinking.
1186 EXPECT_EQ(Region().ToString(), invalidation.ToString());
1187 invalidation.Clear();
1188
1189 UpdateWholePile();
1190 UpdateAndExpandInvalidation(
1191 &invalidation, grow_both_tiling_size, gfx::Rect(1, 1));
1192
1193 // We should have a recording for every tile.
1194 EXPECT_EQ(8, pile_->tiling().num_tiles_x());
1195 EXPECT_EQ(8, pile_->tiling().num_tiles_y());
1196 for (int i = 0; i < pile_->tiling().num_tiles_x(); ++i) {
1197 for (int j = 0; j < pile_->tiling().num_tiles_y(); ++j) {
1198 TestPicturePile::PictureMapKey key(i, j);
1199 TestPicturePile::PictureMap& map = pile_->picture_map();
1200 TestPicturePile::PictureMap::iterator it = map.find(key);
1201 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1202 }
1203 }
1204
1205 // We invalidated the newly exposed pixels on the bottom row and right column
1206 // of tiles.
1207 expected_invalidation = SubtractRegions(gfx::Rect(grow_both_tiling_size),
1208 gfx::Rect(base_tiling_size));
1209 Region bottom_row_and_right_column_new_pixels = SubtractRegions(
1210 UnionRegions(gfx::UnionRects(pile_->tiling().TileBounds(0, 5),
1211 pile_->tiling().TileBounds(5, 5)),
1212 gfx::UnionRects(pile_->tiling().TileBounds(5, 0),
1213 pile_->tiling().TileBounds(5, 5))),
1214 gfx::Rect(base_tiling_size));
1215 EXPECT_TRUE(
1216 expected_invalidation.Contains(bottom_row_and_right_column_new_pixels));
1217 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1218 invalidation.Clear();
1219
1220 UpdateWholePile();
1221 UpdateAndExpandInvalidation(&invalidation, base_tiling_size, gfx::Rect());
1222
1223 // We should have lost the recordings that are now outside the tiling only.
1224 EXPECT_EQ(6, pile_->tiling().num_tiles_x());
1225 EXPECT_EQ(6, pile_->tiling().num_tiles_y());
1226 for (int i = 0; i < pile_->tiling().num_tiles_x(); ++i) {
1227 for (int j = 0; j < pile_->tiling().num_tiles_y(); ++j) {
1228 TestPicturePile::PictureMapKey key(i, j);
1229 TestPicturePile::PictureMap& map = pile_->picture_map();
1230 TestPicturePile::PictureMap::iterator it = map.find(key);
1231 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1232 }
1233 }
1234
1235 // No invalidation when shrinking.
1236 EXPECT_EQ(Region().ToString(), invalidation.ToString());
1237 invalidation.Clear();
1238}
1239
1240TEST_F(PicturePileTest, SmallResizePileInsideInterestRect) {
1241 // This size chosen to be small enough that all the rects below fit inside the
1242 // the interest rect, so they are smaller than kPixelDistanceToRecord in each
1243 // dimension.
1244 int tile_size = 100;
1245 gfx::Size base_tiling_size(5 * tile_size, 5 * tile_size);
1246 gfx::Size grow_down_tiling_size(5 * tile_size, 5 * tile_size + 5);
1247 gfx::Size grow_right_tiling_size(5 * tile_size + 5, 5 * tile_size);
1248 gfx::Size grow_both_tiling_size(5 * tile_size + 5, 5 * tile_size + 5);
1249
1250 Region invalidation;
1251 Region expected_invalidation;
1252
1253 pile_->tiling().SetMaxTextureSize(gfx::Size(tile_size, tile_size));
1254 SetTilingSize(base_tiling_size);
1255
1256 // We should have a recording for every tile.
1257 EXPECT_EQ(6, pile_->tiling().num_tiles_x());
1258 EXPECT_EQ(6, pile_->tiling().num_tiles_y());
1259 for (int i = 0; i < pile_->tiling().num_tiles_x(); ++i) {
1260 for (int j = 0; j < pile_->tiling().num_tiles_y(); ++j) {
1261 TestPicturePile::PictureMapKey key(i, j);
1262 TestPicturePile::PictureMap& map = pile_->picture_map();
1263 TestPicturePile::PictureMap::iterator it = map.find(key);
1264 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1265 }
1266 }
1267
1268 UpdateAndExpandInvalidation(
1269 &invalidation, grow_down_tiling_size, gfx::Rect(1, 1));
1270
1271 // We should have a recording for every tile.
1272 EXPECT_EQ(6, pile_->tiling().num_tiles_x());
1273 EXPECT_EQ(6, pile_->tiling().num_tiles_y());
1274 for (int i = 0; i < pile_->tiling().num_tiles_x(); ++i) {
1275 for (int j = 0; j < pile_->tiling().num_tiles_y(); ++j) {
1276 TestPicturePile::PictureMapKey key(i, j);
1277 TestPicturePile::PictureMap& map = pile_->picture_map();
1278 TestPicturePile::PictureMap::iterator it = map.find(key);
1279 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1280 }
1281 }
1282
1283 // We invalidated the newly exposed pixels.
1284 expected_invalidation = SubtractRegions(gfx::Rect(grow_down_tiling_size),
1285 gfx::Rect(base_tiling_size));
1286 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1287 invalidation.Clear();
1288
1289 UpdateWholePile();
1290 UpdateAndExpandInvalidation(&invalidation, base_tiling_size, gfx::Rect(1, 1));
1291
1292 // We should have a recording for every tile.
1293 EXPECT_EQ(6, pile_->tiling().num_tiles_x());
1294 EXPECT_EQ(6, pile_->tiling().num_tiles_y());
1295 for (int i = 0; i < pile_->tiling().num_tiles_x(); ++i) {
1296 for (int j = 0; j < pile_->tiling().num_tiles_y(); ++j) {
1297 TestPicturePile::PictureMapKey key(i, j);
1298 TestPicturePile::PictureMap& map = pile_->picture_map();
1299 TestPicturePile::PictureMap::iterator it = map.find(key);
1300 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1301 }
1302 }
1303
1304 // No invalidation when shrinking.
1305 EXPECT_EQ(Region().ToString(), invalidation.ToString());
1306 invalidation.Clear();
1307
1308 UpdateWholePile();
1309 UpdateAndExpandInvalidation(
1310 &invalidation, grow_right_tiling_size, gfx::Rect(1, 1));
1311
1312 // We should have a recording for every tile.
1313 EXPECT_EQ(6, pile_->tiling().num_tiles_x());
1314 EXPECT_EQ(6, pile_->tiling().num_tiles_y());
1315 for (int i = 0; i < pile_->tiling().num_tiles_x(); ++i) {
1316 for (int j = 0; j < pile_->tiling().num_tiles_y(); ++j) {
1317 TestPicturePile::PictureMapKey key(i, j);
1318 TestPicturePile::PictureMap& map = pile_->picture_map();
1319 TestPicturePile::PictureMap::iterator it = map.find(key);
1320 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1321 }
1322 }
1323
1324 // We invalidated the newly exposed pixels.
1325 expected_invalidation = SubtractRegions(gfx::Rect(grow_right_tiling_size),
1326 gfx::Rect(base_tiling_size));
1327 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1328 invalidation.Clear();
1329
1330 UpdateWholePile();
1331 UpdateAndExpandInvalidation(&invalidation, base_tiling_size, gfx::Rect(1, 1));
1332
1333 // We should have lost the recordings that are now outside the tiling only.
1334 EXPECT_EQ(6, pile_->tiling().num_tiles_x());
1335 EXPECT_EQ(6, pile_->tiling().num_tiles_y());
1336 for (int i = 0; i < pile_->tiling().num_tiles_x(); ++i) {
1337 for (int j = 0; j < pile_->tiling().num_tiles_y(); ++j) {
1338 TestPicturePile::PictureMapKey key(i, j);
1339 TestPicturePile::PictureMap& map = pile_->picture_map();
1340 TestPicturePile::PictureMap::iterator it = map.find(key);
1341 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1342 }
1343 }
1344
1345 // No invalidation when shrinking.
1346 EXPECT_EQ(Region().ToString(), invalidation.ToString());
1347 invalidation.Clear();
1348
1349 UpdateWholePile();
1350 UpdateAndExpandInvalidation(
1351 &invalidation, grow_both_tiling_size, gfx::Rect(1, 1));
1352
1353 // We should have a recording for every tile.
1354 EXPECT_EQ(6, pile_->tiling().num_tiles_x());
1355 EXPECT_EQ(6, pile_->tiling().num_tiles_y());
1356 for (int i = 0; i < pile_->tiling().num_tiles_x(); ++i) {
1357 for (int j = 0; j < pile_->tiling().num_tiles_y(); ++j) {
1358 TestPicturePile::PictureMapKey key(i, j);
1359 TestPicturePile::PictureMap& map = pile_->picture_map();
1360 TestPicturePile::PictureMap::iterator it = map.find(key);
1361 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1362 }
1363 }
1364
1365 // We invalidated the newly exposed pixels.
1366 expected_invalidation = SubtractRegions(gfx::Rect(grow_both_tiling_size),
1367 gfx::Rect(base_tiling_size));
1368 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1369 invalidation.Clear();
1370
1371 UpdateWholePile();
1372 UpdateAndExpandInvalidation(&invalidation, base_tiling_size, gfx::Rect());
1373
1374 // We should have lost the recordings that are now outside the tiling only.
1375 EXPECT_EQ(6, pile_->tiling().num_tiles_x());
1376 EXPECT_EQ(6, pile_->tiling().num_tiles_y());
1377 for (int i = 0; i < pile_->tiling().num_tiles_x(); ++i) {
1378 for (int j = 0; j < pile_->tiling().num_tiles_y(); ++j) {
1379 TestPicturePile::PictureMapKey key(i, j);
1380 TestPicturePile::PictureMap& map = pile_->picture_map();
1381 TestPicturePile::PictureMap::iterator it = map.find(key);
1382 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1383 }
1384 }
1385
1386 // No invalidation when shrinking.
1387 EXPECT_EQ(Region().ToString(), invalidation.ToString());
1388 invalidation.Clear();
1389}
1390
1391TEST_F(PicturePileTest, SolidRectangleIsSolid) {
1392 // If the client has no contents, the solid state will be true.
1393 Region invalidation1(tiling_rect());
1394 UpdateAndExpandInvalidation(&invalidation1, tiling_size(), tiling_rect());
1395 EXPECT_TRUE(pile_->is_solid_color());
1396 EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), pile_->solid_color());
1397
1398 // If there is a single rect that covers the view, the solid
1399 // state will be true.
1400 SkPaint paint;
1401 paint.setColor(SK_ColorCYAN);
1402 client_.add_draw_rect(tiling_rect(), paint);
1403 Region invalidation2(tiling_rect());
1404 UpdateAndExpandInvalidation(&invalidation2, tiling_size(), tiling_rect());
1405 EXPECT_TRUE(pile_->is_solid_color());
1406 EXPECT_EQ(SK_ColorCYAN, pile_->solid_color());
1407
1408 // If a second smaller rect is draw that doesn't cover the viewport
1409 // completely, the solid state will be false.
1410 gfx::Rect smallRect = tiling_rect();
1411 smallRect.Inset(10, 10, 10, 10);
1412 client_.add_draw_rect(smallRect, paint);
1413 Region invalidation3(tiling_rect());
1414 UpdateAndExpandInvalidation(&invalidation3, tiling_size(), tiling_rect());
1415 EXPECT_FALSE(pile_->is_solid_color());
1416
1417 // If a third rect is drawn over everything, we should be solid again.
1418 paint.setColor(SK_ColorRED);
1419 client_.add_draw_rect(tiling_rect(), paint);
1420 Region invalidation4(tiling_rect());
1421 UpdateAndExpandInvalidation(&invalidation4, tiling_size(), tiling_rect());
1422 EXPECT_TRUE(pile_->is_solid_color());
1423 EXPECT_EQ(SK_ColorRED, pile_->solid_color());
1424
1425 // If we draw too many, we don't bother doing the analysis and we should no
1426 // longer be in a solid state. There are 8 rects, two clips and a translate.
1427 client_.add_draw_rect(tiling_rect(), paint);
1428 client_.add_draw_rect(tiling_rect(), paint);
1429 client_.add_draw_rect(tiling_rect(), paint);
1430 client_.add_draw_rect(tiling_rect(), paint);
1431 client_.add_draw_rect(tiling_rect(), paint);
1432 Region invalidation5(tiling_rect());
1433 UpdateAndExpandInvalidation(&invalidation5, tiling_size(), tiling_rect());
1434 EXPECT_FALSE(pile_->is_solid_color());
1435}
1436
1437} // namespace
1438} // namespace cc