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