1 // Copyright 2011 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.
5 #include "cc/trees/damage_tracker.h"
7 #include "cc/base/math_util.h"
8 #include "cc/layers/layer_impl.h"
9 #include "cc/output/filter_operation.h"
10 #include "cc/output/filter_operations.h"
11 #include "cc/test/fake_impl_proxy.h"
12 #include "cc/test/fake_layer_tree_host_impl.h"
13 #include "cc/test/geometry_test_utils.h"
14 #include "cc/test/test_shared_bitmap_manager.h"
15 #include "cc/trees/layer_tree_host_common.h"
16 #include "cc/trees/single_thread_proxy.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 #include "third_party/skia/include/effects/SkBlurImageFilter.h"
19 #include "ui/gfx/geometry/quad_f.h"
20 #include "ui/gfx/geometry/rect_conversions.h"
25 void ExecuteCalculateDrawProperties(LayerImpl
* root
,
26 LayerImplList
* render_surface_layer_list
) {
27 // Sanity check: The test itself should create the root layer's render
28 // surface, so that the surface (and its damage tracker) can
29 // persist across multiple calls to this function.
30 ASSERT_TRUE(root
->render_surface());
31 ASSERT_FALSE(render_surface_layer_list
->size());
33 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(root
);
34 LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting
inputs(
35 root
, root
->bounds(), render_surface_layer_list
);
36 LayerTreeHostCommon::CalculateDrawProperties(&inputs
);
39 void ClearDamageForAllSurfaces(LayerImpl
* layer
) {
40 if (layer
->render_surface())
41 layer
->render_surface()->damage_tracker()->DidDrawDamagedArea();
43 // Recursively clear damage for any existing surface.
44 for (size_t i
= 0; i
< layer
->children().size(); ++i
)
45 ClearDamageForAllSurfaces(layer
->children()[i
]);
48 void EmulateDrawingOneFrame(LayerImpl
* root
) {
49 // This emulates only steps that are relevant to testing the damage tracker:
50 // 1. computing the render passes and layerlists
51 // 2. updating all damage trackers in the correct order
52 // 3. resetting all update_rects and property_changed flags for all layers
55 LayerImplList render_surface_layer_list
;
56 ExecuteCalculateDrawProperties(root
, &render_surface_layer_list
);
58 // Iterate back-to-front, so that damage correctly propagates from descendant
59 // surfaces to ancestors.
60 for (int i
= render_surface_layer_list
.size() - 1; i
>= 0; --i
) {
61 RenderSurfaceImpl
* target_surface
=
62 render_surface_layer_list
[i
]->render_surface();
63 target_surface
->damage_tracker()->UpdateDamageTrackingState(
64 target_surface
->layer_list(),
65 target_surface
->OwningLayerId(),
66 target_surface
->SurfacePropertyChangedOnlyFromDescendant(),
67 target_surface
->content_rect(),
68 render_surface_layer_list
[i
]->mask_layer(),
69 render_surface_layer_list
[i
]->filters());
72 root
->ResetAllChangeTrackingForSubtree();
75 class DamageTrackerTest
: public testing::Test
{
77 DamageTrackerTest() : host_impl_(&proxy_
, &shared_bitmap_manager_
) {}
79 scoped_ptr
<LayerImpl
> CreateTestTreeWithOneSurface() {
80 scoped_ptr
<LayerImpl
> root
=
81 LayerImpl::Create(host_impl_
.active_tree(), 1);
82 scoped_ptr
<LayerImpl
> child
=
83 LayerImpl::Create(host_impl_
.active_tree(), 2);
85 root
->SetPosition(gfx::PointF());
86 root
->SetBounds(gfx::Size(500, 500));
87 root
->SetContentBounds(gfx::Size(500, 500));
88 root
->SetDrawsContent(true);
89 root
->CreateRenderSurface();
90 root
->render_surface()->SetContentRect(gfx::Rect(0, 0, 500, 500));
92 child
->SetPosition(gfx::PointF(100.f
, 100.f
));
93 child
->SetBounds(gfx::Size(30, 30));
94 child
->SetContentBounds(gfx::Size(30, 30));
95 child
->SetDrawsContent(true);
96 root
->AddChild(child
.Pass());
101 scoped_ptr
<LayerImpl
> CreateTestTreeWithTwoSurfaces() {
102 // This test tree has two render surfaces: one for the root, and one for
103 // child1. Additionally, the root has a second child layer, and child1 has
104 // two children of its own.
106 scoped_ptr
<LayerImpl
> root
=
107 LayerImpl::Create(host_impl_
.active_tree(), 1);
108 scoped_ptr
<LayerImpl
> child1
=
109 LayerImpl::Create(host_impl_
.active_tree(), 2);
110 scoped_ptr
<LayerImpl
> child2
=
111 LayerImpl::Create(host_impl_
.active_tree(), 3);
112 scoped_ptr
<LayerImpl
> grand_child1
=
113 LayerImpl::Create(host_impl_
.active_tree(), 4);
114 scoped_ptr
<LayerImpl
> grand_child2
=
115 LayerImpl::Create(host_impl_
.active_tree(), 5);
117 root
->SetPosition(gfx::PointF());
118 root
->SetBounds(gfx::Size(500, 500));
119 root
->SetContentBounds(gfx::Size(500, 500));
120 root
->SetDrawsContent(true);
121 root
->CreateRenderSurface();
122 root
->render_surface()->SetContentRect(gfx::Rect(0, 0, 500, 500));
124 child1
->SetPosition(gfx::PointF(100.f
, 100.f
));
125 child1
->SetBounds(gfx::Size(30, 30));
126 child1
->SetContentBounds(gfx::Size(30, 30));
127 // With a child that draws_content, opacity will cause the layer to create
128 // its own RenderSurface. This layer does not draw, but is intended to
129 // create its own RenderSurface. TODO: setting opacity and
130 // ForceRenderSurface may be redundant here.
131 child1
->SetOpacity(0.5f
);
132 child1
->SetDrawsContent(false);
133 child1
->SetForceRenderSurface(true);
135 child2
->SetPosition(gfx::PointF(11.f
, 11.f
));
136 child2
->SetBounds(gfx::Size(18, 18));
137 child2
->SetContentBounds(gfx::Size(18, 18));
138 child2
->SetDrawsContent(true);
140 grand_child1
->SetPosition(gfx::PointF(200.f
, 200.f
));
141 grand_child1
->SetBounds(gfx::Size(6, 8));
142 grand_child1
->SetContentBounds(gfx::Size(6, 8));
143 grand_child1
->SetDrawsContent(true);
145 grand_child2
->SetPosition(gfx::PointF(190.f
, 190.f
));
146 grand_child2
->SetBounds(gfx::Size(6, 8));
147 grand_child2
->SetContentBounds(gfx::Size(6, 8));
148 grand_child2
->SetDrawsContent(true);
150 child1
->AddChild(grand_child1
.Pass());
151 child1
->AddChild(grand_child2
.Pass());
152 root
->AddChild(child1
.Pass());
153 root
->AddChild(child2
.Pass());
158 scoped_ptr
<LayerImpl
> CreateAndSetUpTestTreeWithOneSurface() {
159 scoped_ptr
<LayerImpl
> root
= CreateTestTreeWithOneSurface();
161 // Setup includes going past the first frame which always damages
162 // everything, so that we can actually perform specific tests.
163 EmulateDrawingOneFrame(root
.get());
168 scoped_ptr
<LayerImpl
> CreateAndSetUpTestTreeWithTwoSurfaces() {
169 scoped_ptr
<LayerImpl
> root
= CreateTestTreeWithTwoSurfaces();
171 // Setup includes going past the first frame which always damages
172 // everything, so that we can actually perform specific tests.
173 EmulateDrawingOneFrame(root
.get());
179 FakeImplProxy proxy_
;
180 TestSharedBitmapManager shared_bitmap_manager_
;
181 FakeLayerTreeHostImpl host_impl_
;
184 TEST_F(DamageTrackerTest
, SanityCheckTestTreeWithOneSurface
) {
185 // Sanity check that the simple test tree will actually produce the expected
186 // render surfaces and layer lists.
188 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
190 EXPECT_EQ(2u, root
->render_surface()->layer_list().size());
191 EXPECT_EQ(1, root
->render_surface()->layer_list()[0]->id());
192 EXPECT_EQ(2, root
->render_surface()->layer_list()[1]->id());
194 gfx::Rect root_damage_rect
=
195 root
->render_surface()->damage_tracker()->current_damage_rect();
197 EXPECT_EQ(gfx::Rect(500, 500).ToString(), root_damage_rect
.ToString());
200 TEST_F(DamageTrackerTest
, SanityCheckTestTreeWithTwoSurfaces
) {
201 // Sanity check that the complex test tree will actually produce the expected
202 // render surfaces and layer lists.
204 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithTwoSurfaces();
206 LayerImpl
* child1
= root
->children()[0];
207 LayerImpl
* child2
= root
->children()[1];
208 gfx::Rect child_damage_rect
=
209 child1
->render_surface()->damage_tracker()->current_damage_rect();
210 gfx::Rect root_damage_rect
=
211 root
->render_surface()->damage_tracker()->current_damage_rect();
213 ASSERT_TRUE(child1
->render_surface());
214 EXPECT_FALSE(child2
->render_surface());
215 EXPECT_EQ(3u, root
->render_surface()->layer_list().size());
216 EXPECT_EQ(2u, child1
->render_surface()->layer_list().size());
218 // The render surface for child1 only has a content_rect that encloses
219 // grand_child1 and grand_child2, because child1 does not draw content.
220 EXPECT_EQ(gfx::Rect(190, 190, 16, 18).ToString(),
221 child_damage_rect
.ToString());
222 EXPECT_EQ(gfx::Rect(500, 500).ToString(), root_damage_rect
.ToString());
225 TEST_F(DamageTrackerTest
, VerifyDamageForUpdateRects
) {
226 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
227 LayerImpl
* child
= root
->children()[0];
229 // CASE 1: Setting the update rect should cause the corresponding damage to
231 ClearDamageForAllSurfaces(root
.get());
232 child
->SetUpdateRect(gfx::Rect(10, 11, 12, 13));
233 EmulateDrawingOneFrame(root
.get());
235 // Damage position on the surface should be: position of update_rect (10, 11)
236 // relative to the child (100, 100).
237 gfx::Rect root_damage_rect
=
238 root
->render_surface()->damage_tracker()->current_damage_rect();
239 EXPECT_EQ(gfx::Rect(110, 111, 12, 13).ToString(),
240 root_damage_rect
.ToString());
242 // CASE 2: The same update rect twice in a row still produces the same
244 ClearDamageForAllSurfaces(root
.get());
245 child
->SetUpdateRect(gfx::Rect(10, 11, 12, 13));
246 EmulateDrawingOneFrame(root
.get());
248 root
->render_surface()->damage_tracker()->current_damage_rect();
249 EXPECT_EQ(gfx::Rect(110, 111, 12, 13).ToString(),
250 root_damage_rect
.ToString());
252 // CASE 3: Setting a different update rect should cause damage on the new
253 // update region, but no additional exposed old region.
254 ClearDamageForAllSurfaces(root
.get());
255 child
->SetUpdateRect(gfx::Rect(20, 25, 1, 2));
256 EmulateDrawingOneFrame(root
.get());
258 // Damage position on the surface should be: position of update_rect (20, 25)
259 // relative to the child (100, 100).
261 root
->render_surface()->damage_tracker()->current_damage_rect();
262 EXPECT_EQ(gfx::Rect(120, 125, 1, 2).ToString(), root_damage_rect
.ToString());
265 TEST_F(DamageTrackerTest
, VerifyDamageForLayerDamageRects
) {
266 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
267 LayerImpl
* child
= root
->children()[0];
269 // CASE 1: Adding the layer damage rect should cause the corresponding damage
271 ClearDamageForAllSurfaces(root
.get());
272 child
->AddDamageRect(gfx::RectF(10.f
, 11.f
, 12.f
, 13.f
));
273 EmulateDrawingOneFrame(root
.get());
275 // Damage position on the surface should be: position of layer damage_rect
276 // (10, 11) relative to the child (100, 100).
277 gfx::Rect root_damage_rect
=
278 root
->render_surface()->damage_tracker()->current_damage_rect();
279 EXPECT_EQ(true, root_damage_rect
.Contains(gfx::Rect(110, 111, 12, 13)));
281 // CASE 2: The same layer damage rect twice in a row still produces the same
283 ClearDamageForAllSurfaces(root
.get());
284 child
->AddDamageRect(gfx::RectF(10.f
, 11.f
, 12.f
, 13.f
));
285 EmulateDrawingOneFrame(root
.get());
287 root
->render_surface()->damage_tracker()->current_damage_rect();
288 EXPECT_EQ(true, root_damage_rect
.Contains(gfx::Rect(110, 111, 12, 13)));
290 // CASE 3: Adding a different layer damage rect should cause damage on the
291 // new damaged region, but no additional exposed old region.
292 ClearDamageForAllSurfaces(root
.get());
293 child
->AddDamageRect(gfx::RectF(20.f
, 25.f
, 1.f
, 2.f
));
294 EmulateDrawingOneFrame(root
.get());
296 // Damage position on the surface should be: position of layer damage_rect
297 // (20, 25) relative to the child (100, 100).
299 root
->render_surface()->damage_tracker()->current_damage_rect();
300 EXPECT_EQ(true, root_damage_rect
.Contains(gfx::Rect(120, 125, 1, 2)));
302 // CASE 4: Adding multiple layer damage rects should cause a unified
303 // damage on root damage rect.
304 ClearDamageForAllSurfaces(root
.get());
305 child
->AddDamageRect(gfx::RectF(20.f
, 25.f
, 1.f
, 2.f
));
306 child
->AddDamageRect(gfx::RectF(10.f
, 15.f
, 3.f
, 4.f
));
307 EmulateDrawingOneFrame(root
.get());
309 // Damage position on the surface should be: position of layer damage_rect
310 // (20, 25) relative to the child (100, 100).
312 root
->render_surface()->damage_tracker()->current_damage_rect();
313 EXPECT_EQ(true, root_damage_rect
.Contains(gfx::Rect(120, 125, 1, 2)));
314 EXPECT_EQ(true, root_damage_rect
.Contains(gfx::Rect(110, 115, 3, 4)));
317 TEST_F(DamageTrackerTest
, VerifyDamageForLayerUpdateAndDamageRects
) {
318 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
319 LayerImpl
* child
= root
->children()[0];
321 // CASE 1: Adding the layer damage rect and update rect should cause the
322 // corresponding damage to the surface.
323 ClearDamageForAllSurfaces(root
.get());
324 child
->AddDamageRect(gfx::RectF(5.f
, 6.f
, 12.f
, 13.f
));
325 child
->SetUpdateRect(gfx::Rect(15, 16, 14, 10));
326 EmulateDrawingOneFrame(root
.get());
328 // Damage position on the surface should be: position of unified layer
329 // damage_rect and update rect (5, 6)
330 // relative to the child (100, 100).
331 gfx::Rect root_damage_rect
=
332 root
->render_surface()->damage_tracker()->current_damage_rect();
333 EXPECT_EQ(true, root_damage_rect
.Contains(gfx::Rect(105, 106, 24, 20)));
335 // CASE 2: The same layer damage rect and update rect twice in a row still
336 // produces the same damage.
337 ClearDamageForAllSurfaces(root
.get());
338 child
->AddDamageRect(gfx::RectF(10.f
, 11.f
, 12.f
, 13.f
));
339 child
->SetUpdateRect(gfx::Rect(10, 11, 14, 15));
340 EmulateDrawingOneFrame(root
.get());
342 root
->render_surface()->damage_tracker()->current_damage_rect();
343 EXPECT_EQ(true, root_damage_rect
.Contains(gfx::Rect(110, 111, 14, 15)));
345 // CASE 3: Adding a different layer damage rect and update rect should cause
346 // damage on the new damaged region, but no additional exposed old region.
347 ClearDamageForAllSurfaces(root
.get());
348 child
->AddDamageRect(gfx::RectF(20.f
, 25.f
, 2.f
, 3.f
));
349 child
->SetUpdateRect(gfx::Rect(5, 10, 7, 8));
350 EmulateDrawingOneFrame(root
.get());
352 // Damage position on the surface should be: position of unified layer damage
353 // rect and update rect (5, 10) relative to the child (100, 100).
355 root
->render_surface()->damage_tracker()->current_damage_rect();
356 EXPECT_EQ(true, root_damage_rect
.Contains(gfx::Rect(105, 110, 17, 18)));
359 TEST_F(DamageTrackerTest
, VerifyDamageForPropertyChanges
) {
360 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
361 LayerImpl
* child
= root
->children()[0];
363 // CASE 1: The layer's property changed flag takes priority over update rect.
365 ClearDamageForAllSurfaces(root
.get());
366 child
->SetUpdateRect(gfx::Rect(10, 11, 12, 13));
367 child
->SetOpacity(0.5f
);
368 EmulateDrawingOneFrame(root
.get());
370 // Sanity check - we should not have accidentally created a separate render
371 // surface for the translucent layer.
372 ASSERT_FALSE(child
->render_surface());
373 ASSERT_EQ(2u, root
->render_surface()->layer_list().size());
375 // Damage should be the entire child layer in target_surface space.
376 gfx::Rect expected_rect
= gfx::Rect(100, 100, 30, 30);
377 gfx::Rect root_damage_rect
=
378 root
->render_surface()->damage_tracker()->current_damage_rect();
379 EXPECT_EQ(expected_rect
.ToString(), root_damage_rect
.ToString());
381 // CASE 2: If a layer moves due to property change, it damages both the new
382 // location and the old (exposed) location. The old location is the
383 // entire old layer, not just the update_rect.
385 // Cycle one frame of no change, just to sanity check that the next rect is
386 // not because of the old damage state.
387 ClearDamageForAllSurfaces(root
.get());
388 EmulateDrawingOneFrame(root
.get());
390 root
->render_surface()->damage_tracker()->current_damage_rect();
391 EXPECT_TRUE(root_damage_rect
.IsEmpty());
393 // Then, test the actual layer movement.
394 ClearDamageForAllSurfaces(root
.get());
395 child
->SetPosition(gfx::PointF(200.f
, 230.f
));
396 EmulateDrawingOneFrame(root
.get());
398 // Expect damage to be the combination of the previous one and the new one.
399 expected_rect
.Union(gfx::Rect(200, 230, 30, 30));
401 root
->render_surface()->damage_tracker()->current_damage_rect();
402 EXPECT_FLOAT_RECT_EQ(expected_rect
, root_damage_rect
);
405 TEST_F(DamageTrackerTest
, VerifyDamageForTransformedLayer
) {
406 // If a layer is transformed, the damage rect should still enclose the entire
407 // transformed layer.
409 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
410 LayerImpl
* child
= root
->children()[0];
412 gfx::Transform rotation
;
413 rotation
.Rotate(45.0);
415 ClearDamageForAllSurfaces(root
.get());
416 child
->SetTransformOrigin(gfx::Point3F(
417 child
->bounds().width() * 0.5f
, child
->bounds().height() * 0.5f
, 0.f
));
418 child
->SetPosition(gfx::PointF(85.f
, 85.f
));
419 EmulateDrawingOneFrame(root
.get());
421 // Sanity check that the layer actually moved to (85, 85), damaging its old
422 // location and new location.
423 gfx::Rect root_damage_rect
=
424 root
->render_surface()->damage_tracker()->current_damage_rect();
425 EXPECT_EQ(gfx::Rect(85, 85, 45, 45).ToString(), root_damage_rect
.ToString());
427 // With the anchor on the layer's center, now we can test the rotation more
428 // intuitively, since it applies about the layer's anchor.
429 ClearDamageForAllSurfaces(root
.get());
430 child
->SetTransform(rotation
);
431 EmulateDrawingOneFrame(root
.get());
433 // Since the child layer is square, rotation by 45 degrees about the center
434 // should increase the size of the expected rect by sqrt(2), centered around
435 // (100, 100). The old exposed region should be fully contained in the new
437 float expected_width
= 30.f
* sqrt(2.f
);
438 float expected_position
= 100.f
- 0.5f
* expected_width
;
439 gfx::Rect expected_rect
= gfx::ToEnclosingRect(gfx::RectF(
440 expected_position
, expected_position
, expected_width
, expected_width
));
442 root
->render_surface()->damage_tracker()->current_damage_rect();
443 EXPECT_EQ(expected_rect
.ToString(), root_damage_rect
.ToString());
446 TEST_F(DamageTrackerTest
, VerifyDamageForPerspectiveClippedLayer
) {
447 // If a layer has a perspective transform that causes w < 0, then not
448 // clipping the layer can cause an invalid damage rect. This test checks that
449 // the w < 0 case is tracked properly.
451 // The transform is constructed so that if w < 0 clipping is not performed,
452 // the incorrect rect will be very small, specifically: position (500.972504,
453 // 498.544617) and size 0.056610 x 2.910767. Instead, the correctly
454 // transformed rect should actually be very huge (i.e. in theory, -infinity
455 // on the left), and positioned so that the right-most bound rect will be
456 // approximately 501 units in root surface space.
459 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
460 LayerImpl
* child
= root
->children()[0];
462 gfx::Transform transform
;
463 transform
.Translate3d(500.0, 500.0, 0.0);
464 transform
.ApplyPerspectiveDepth(1.0);
465 transform
.RotateAboutYAxis(45.0);
466 transform
.Translate3d(-50.0, -50.0, 0.0);
469 child
->SetPosition(gfx::PointF(0.f
, 0.f
));
470 child
->SetBounds(gfx::Size(100, 100));
471 child
->SetContentBounds(gfx::Size(100, 100));
472 child
->SetTransform(transform
);
473 EmulateDrawingOneFrame(root
.get());
475 // Sanity check that the child layer's bounds would actually get clipped by
476 // w < 0, otherwise this test is not actually testing the intended scenario.
477 gfx::QuadF
test_quad(gfx::RectF(gfx::PointF(), gfx::SizeF(100.f
, 100.f
)));
478 bool clipped
= false;
479 MathUtil::MapQuad(transform
, test_quad
, &clipped
);
480 EXPECT_TRUE(clipped
);
482 // Damage the child without moving it.
483 ClearDamageForAllSurfaces(root
.get());
484 child
->SetOpacity(0.5f
);
485 EmulateDrawingOneFrame(root
.get());
487 // The expected damage should cover the entire root surface (500x500), but we
488 // don't care whether the damage rect was clamped or is larger than the
489 // surface for this test.
490 gfx::Rect root_damage_rect
=
491 root
->render_surface()->damage_tracker()->current_damage_rect();
492 gfx::Rect damage_we_care_about
= gfx::Rect(gfx::Size(500, 500));
493 EXPECT_TRUE(root_damage_rect
.Contains(damage_we_care_about
));
496 TEST_F(DamageTrackerTest
, VerifyDamageForBlurredSurface
) {
497 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithTwoSurfaces();
498 LayerImpl
* surface
= root
->children()[0];
499 LayerImpl
* child
= surface
->children()[0];
501 FilterOperations filters
;
502 filters
.Append(FilterOperation::CreateBlurFilter(5.f
));
503 int outset_top
, outset_right
, outset_bottom
, outset_left
;
504 filters
.GetOutsets(&outset_top
, &outset_right
, &outset_bottom
, &outset_left
);
506 // Setting the filter will damage the whole surface.
507 ClearDamageForAllSurfaces(root
.get());
508 surface
->SetFilters(filters
);
509 EmulateDrawingOneFrame(root
.get());
511 // Setting the update rect should cause the corresponding damage to the
512 // surface, blurred based on the size of the blur filter.
513 ClearDamageForAllSurfaces(root
.get());
514 child
->SetUpdateRect(gfx::Rect(1, 2, 3, 4));
515 EmulateDrawingOneFrame(root
.get());
517 // Damage position on the surface should be: position of update_rect (1, 2)
518 // relative to the child (300, 300), but expanded by the blur outsets.
519 gfx::Rect root_damage_rect
=
520 root
->render_surface()->damage_tracker()->current_damage_rect();
521 gfx::Rect expected_damage_rect
= gfx::Rect(301, 302, 3, 4);
523 expected_damage_rect
.Inset(-outset_left
,
527 EXPECT_EQ(expected_damage_rect
.ToString(), root_damage_rect
.ToString());
530 TEST_F(DamageTrackerTest
, VerifyDamageForImageFilter
) {
531 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
532 LayerImpl
* child
= root
->children()[0];
533 gfx::Rect root_damage_rect
, child_damage_rect
;
535 // Allow us to set damage on child too.
536 child
->SetDrawsContent(true);
538 skia::RefPtr
<SkImageFilter
> filter
= skia::AdoptRef(
539 SkBlurImageFilter::Create(SkIntToScalar(2), SkIntToScalar(2)));
540 FilterOperations filters
;
541 filters
.Append(FilterOperation::CreateReferenceFilter(filter
));
543 // Setting the filter will damage the whole surface.
544 ClearDamageForAllSurfaces(root
.get());
545 child
->SetFilters(filters
);
546 EmulateDrawingOneFrame(root
.get());
548 root
->render_surface()->damage_tracker()->current_damage_rect();
550 child
->render_surface()->damage_tracker()->current_damage_rect();
551 EXPECT_EQ(gfx::Rect(100, 100, 30, 30).ToString(),
552 root_damage_rect
.ToString());
553 EXPECT_EQ(gfx::Rect(30, 30).ToString(), child_damage_rect
.ToString());
555 // CASE 1: Setting the update rect should damage the whole surface (for now)
556 ClearDamageForAllSurfaces(root
.get());
557 child
->SetUpdateRect(gfx::Rect(1, 1));
558 EmulateDrawingOneFrame(root
.get());
561 root
->render_surface()->damage_tracker()->current_damage_rect();
563 child
->render_surface()->damage_tracker()->current_damage_rect();
564 EXPECT_EQ(gfx::Rect(100, 100, 30, 30).ToString(),
565 root_damage_rect
.ToString());
566 EXPECT_EQ(gfx::Rect(30.f
, 30.f
).ToString(), child_damage_rect
.ToString());
569 TEST_F(DamageTrackerTest
, VerifyDamageForBackgroundBlurredChild
) {
570 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithTwoSurfaces();
571 LayerImpl
* child1
= root
->children()[0];
572 LayerImpl
* child2
= root
->children()[1];
574 // Allow us to set damage on child1 too.
575 child1
->SetDrawsContent(true);
577 FilterOperations filters
;
578 filters
.Append(FilterOperation::CreateBlurFilter(2.f
));
579 int outset_top
, outset_right
, outset_bottom
, outset_left
;
580 filters
.GetOutsets(&outset_top
, &outset_right
, &outset_bottom
, &outset_left
);
582 // Setting the filter will damage the whole surface.
583 ClearDamageForAllSurfaces(root
.get());
584 child1
->SetBackgroundFilters(filters
);
585 EmulateDrawingOneFrame(root
.get());
587 // CASE 1: Setting the update rect should cause the corresponding damage to
588 // the surface, blurred based on the size of the child's background
590 ClearDamageForAllSurfaces(root
.get());
591 root
->SetUpdateRect(gfx::Rect(297, 297, 2, 2));
592 EmulateDrawingOneFrame(root
.get());
594 gfx::Rect root_damage_rect
=
595 root
->render_surface()->damage_tracker()->current_damage_rect();
596 // Damage position on the surface should be a composition of the damage on
597 // the root and on child2. Damage on the root should be: position of
598 // update_rect (297, 297), but expanded by the blur outsets.
599 gfx::Rect expected_damage_rect
= gfx::Rect(297, 297, 2, 2);
601 expected_damage_rect
.Inset(-outset_left
,
605 EXPECT_EQ(expected_damage_rect
.ToString(), root_damage_rect
.ToString());
607 // CASE 2: Setting the update rect should cause the corresponding damage to
608 // the surface, blurred based on the size of the child's background
609 // blur filter. Since the damage extends to the right/bottom outside
610 // of the blurred layer, only the left/top should end up expanded.
611 ClearDamageForAllSurfaces(root
.get());
612 root
->SetUpdateRect(gfx::Rect(297, 297, 30, 30));
613 EmulateDrawingOneFrame(root
.get());
616 root
->render_surface()->damage_tracker()->current_damage_rect();
617 // Damage position on the surface should be a composition of the damage on
618 // the root and on child2. Damage on the root should be: position of
619 // update_rect (297, 297), but expanded on the left/top by the blur outsets.
620 expected_damage_rect
= gfx::Rect(297, 297, 30, 30);
622 expected_damage_rect
.Inset(-outset_left
,
626 EXPECT_EQ(expected_damage_rect
.ToString(), root_damage_rect
.ToString());
628 // CASE 3: Setting this update rect outside the blurred content_bounds of the
629 // blurred child1 will not cause it to be expanded.
630 ClearDamageForAllSurfaces(root
.get());
631 root
->SetUpdateRect(gfx::Rect(30, 30, 2, 2));
632 EmulateDrawingOneFrame(root
.get());
635 root
->render_surface()->damage_tracker()->current_damage_rect();
636 // Damage on the root should be: position of update_rect (30, 30), not
638 expected_damage_rect
= gfx::Rect(30, 30, 2, 2);
640 EXPECT_EQ(expected_damage_rect
.ToString(), root_damage_rect
.ToString());
642 // CASE 4: Setting this update rect inside the blurred content_bounds but
643 // outside the original content_bounds of the blurred child1 will
644 // cause it to be expanded.
645 ClearDamageForAllSurfaces(root
.get());
646 root
->SetUpdateRect(gfx::Rect(99, 99, 1, 1));
647 EmulateDrawingOneFrame(root
.get());
650 root
->render_surface()->damage_tracker()->current_damage_rect();
651 // Damage on the root should be: position of update_rect (99, 99), expanded by
652 // the blurring on child1, but since it is 1 pixel outside the layer, the
653 // expanding should be reduced by 1.
654 expected_damage_rect
= gfx::Rect(99, 99, 1, 1);
656 expected_damage_rect
.Inset(-outset_left
+ 1,
660 EXPECT_EQ(expected_damage_rect
.ToString(), root_damage_rect
.ToString());
662 // CASE 5: Setting the update rect on child2, which is above child1, will
663 // not get blurred by child1, so it does not need to get expanded.
664 ClearDamageForAllSurfaces(root
.get());
665 child2
->SetUpdateRect(gfx::Rect(1, 1));
666 EmulateDrawingOneFrame(root
.get());
669 root
->render_surface()->damage_tracker()->current_damage_rect();
670 // Damage on child2 should be: position of update_rect offset by the child's
671 // position (11, 11), and not expanded by anything.
672 expected_damage_rect
= gfx::Rect(11, 11, 1, 1);
674 EXPECT_EQ(expected_damage_rect
.ToString(), root_damage_rect
.ToString());
676 // CASE 6: Setting the update rect on child1 will also blur the damage, so
677 // that any pixels needed for the blur are redrawn in the current
679 ClearDamageForAllSurfaces(root
.get());
680 child1
->SetUpdateRect(gfx::Rect(1, 1));
681 EmulateDrawingOneFrame(root
.get());
684 root
->render_surface()->damage_tracker()->current_damage_rect();
685 // Damage on child1 should be: position of update_rect offset by the child's
686 // position (100, 100), and expanded by the damage.
687 expected_damage_rect
= gfx::Rect(100, 100, 1, 1);
689 expected_damage_rect
.Inset(-outset_left
,
693 EXPECT_EQ(expected_damage_rect
.ToString(), root_damage_rect
.ToString());
696 TEST_F(DamageTrackerTest
, VerifyDamageForAddingAndRemovingLayer
) {
697 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
698 LayerImpl
* child1
= root
->children()[0];
700 // CASE 1: Adding a new layer should cause the appropriate damage.
702 ClearDamageForAllSurfaces(root
.get());
704 scoped_ptr
<LayerImpl
> child2
=
705 LayerImpl::Create(host_impl_
.active_tree(), 3);
706 child2
->SetPosition(gfx::PointF(400.f
, 380.f
));
707 child2
->SetBounds(gfx::Size(6, 8));
708 child2
->SetContentBounds(gfx::Size(6, 8));
709 child2
->SetDrawsContent(true);
710 root
->AddChild(child2
.Pass());
712 EmulateDrawingOneFrame(root
.get());
714 // Sanity check - all 3 layers should be on the same render surface; render
715 // surfaces are tested elsewhere.
716 ASSERT_EQ(3u, root
->render_surface()->layer_list().size());
718 gfx::Rect root_damage_rect
=
719 root
->render_surface()->damage_tracker()->current_damage_rect();
720 EXPECT_EQ(gfx::Rect(400, 380, 6, 8).ToString(), root_damage_rect
.ToString());
722 // CASE 2: If the layer is removed, its entire old layer becomes exposed, not
723 // just the last update rect.
725 // Advance one frame without damage so that we know the damage rect is not
726 // leftover from the previous case.
727 ClearDamageForAllSurfaces(root
.get());
728 EmulateDrawingOneFrame(root
.get());
731 root
->render_surface()->damage_tracker()->current_damage_rect();
732 EXPECT_TRUE(root_damage_rect
.IsEmpty());
734 // Then, test removing child1.
735 root
->RemoveChild(child1
);
737 EmulateDrawingOneFrame(root
.get());
740 root
->render_surface()->damage_tracker()->current_damage_rect();
741 EXPECT_EQ(gfx::Rect(100, 100, 30, 30).ToString(),
742 root_damage_rect
.ToString());
745 TEST_F(DamageTrackerTest
, VerifyDamageForNewUnchangedLayer
) {
746 // If child2 is added to the layer tree, but it doesn't have any explicit
747 // damage of its own, it should still indeed damage the target surface.
749 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
751 ClearDamageForAllSurfaces(root
.get());
753 scoped_ptr
<LayerImpl
> child2
=
754 LayerImpl::Create(host_impl_
.active_tree(), 3);
755 child2
->SetPosition(gfx::PointF(400.f
, 380.f
));
756 child2
->SetBounds(gfx::Size(6, 8));
757 child2
->SetContentBounds(gfx::Size(6, 8));
758 child2
->SetDrawsContent(true);
759 child2
->ResetAllChangeTrackingForSubtree();
760 // Sanity check the initial conditions of the test, if these asserts
761 // trigger, it means the test no longer actually covers the intended
763 ASSERT_FALSE(child2
->LayerPropertyChanged());
764 ASSERT_TRUE(child2
->update_rect().IsEmpty());
765 root
->AddChild(child2
.Pass());
767 EmulateDrawingOneFrame(root
.get());
769 // Sanity check - all 3 layers should be on the same render surface; render
770 // surfaces are tested elsewhere.
771 ASSERT_EQ(3u, root
->render_surface()->layer_list().size());
773 gfx::Rect root_damage_rect
=
774 root
->render_surface()->damage_tracker()->current_damage_rect();
775 EXPECT_EQ(gfx::Rect(400, 380, 6, 8).ToString(), root_damage_rect
.ToString());
778 TEST_F(DamageTrackerTest
, VerifyDamageForMultipleLayers
) {
779 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
780 LayerImpl
* child1
= root
->children()[0];
782 // In this test we don't want the above tree manipulation to be considered
783 // part of the same frame.
784 ClearDamageForAllSurfaces(root
.get());
786 scoped_ptr
<LayerImpl
> child2
=
787 LayerImpl::Create(host_impl_
.active_tree(), 3);
788 child2
->SetPosition(gfx::PointF(400.f
, 380.f
));
789 child2
->SetBounds(gfx::Size(6, 8));
790 child2
->SetContentBounds(gfx::Size(6, 8));
791 child2
->SetDrawsContent(true);
792 root
->AddChild(child2
.Pass());
794 LayerImpl
* child2
= root
->children()[1];
795 EmulateDrawingOneFrame(root
.get());
797 // Damaging two layers simultaneously should cause combined damage.
798 // - child1 update rect in surface space: gfx::Rect(100, 100, 1, 2);
799 // - child2 update rect in surface space: gfx::Rect(400, 380, 3, 4);
800 ClearDamageForAllSurfaces(root
.get());
801 child1
->SetUpdateRect(gfx::Rect(1, 2));
802 child2
->SetUpdateRect(gfx::Rect(3, 4));
803 EmulateDrawingOneFrame(root
.get());
804 gfx::Rect root_damage_rect
=
805 root
->render_surface()->damage_tracker()->current_damage_rect();
806 EXPECT_EQ(gfx::Rect(100, 100, 303, 284).ToString(),
807 root_damage_rect
.ToString());
810 TEST_F(DamageTrackerTest
, VerifyDamageForNestedSurfaces
) {
811 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithTwoSurfaces();
812 LayerImpl
* child1
= root
->children()[0];
813 LayerImpl
* child2
= root
->children()[1];
814 LayerImpl
* grand_child1
= root
->children()[0]->children()[0];
815 gfx::Rect child_damage_rect
;
816 gfx::Rect root_damage_rect
;
818 // CASE 1: Damage to a descendant surface should propagate properly to
820 ClearDamageForAllSurfaces(root
.get());
821 grand_child1
->SetOpacity(0.5f
);
822 EmulateDrawingOneFrame(root
.get());
824 child1
->render_surface()->damage_tracker()->current_damage_rect();
826 root
->render_surface()->damage_tracker()->current_damage_rect();
827 EXPECT_EQ(gfx::Rect(200, 200, 6, 8).ToString(), child_damage_rect
.ToString());
828 EXPECT_EQ(gfx::Rect(300, 300, 6, 8).ToString(), root_damage_rect
.ToString());
830 // CASE 2: Same as previous case, but with additional damage elsewhere that
831 // should be properly unioned.
832 // - child1 surface damage in root surface space:
833 // gfx::Rect(300, 300, 6, 8);
834 // - child2 damage in root surface space:
835 // gfx::Rect(11, 11, 18, 18);
836 ClearDamageForAllSurfaces(root
.get());
837 grand_child1
->SetOpacity(0.7f
);
838 child2
->SetOpacity(0.7f
);
839 EmulateDrawingOneFrame(root
.get());
841 child1
->render_surface()->damage_tracker()->current_damage_rect();
843 root
->render_surface()->damage_tracker()->current_damage_rect();
844 EXPECT_EQ(gfx::Rect(200, 200, 6, 8).ToString(), child_damage_rect
.ToString());
845 EXPECT_EQ(gfx::Rect(11, 11, 295, 297).ToString(),
846 root_damage_rect
.ToString());
849 TEST_F(DamageTrackerTest
, VerifyDamageForSurfaceChangeFromDescendantLayer
) {
850 // If descendant layer changes and affects the content bounds of the render
851 // surface, then the entire descendant surface should be damaged, and it
852 // should damage its ancestor surface with the old and new surface regions.
854 // This is a tricky case, since only the first grand_child changes, but the
855 // entire surface should be marked dirty.
857 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithTwoSurfaces();
858 LayerImpl
* child1
= root
->children()[0];
859 LayerImpl
* grand_child1
= root
->children()[0]->children()[0];
860 gfx::Rect child_damage_rect
;
861 gfx::Rect root_damage_rect
;
863 ClearDamageForAllSurfaces(root
.get());
864 grand_child1
->SetPosition(gfx::PointF(195.f
, 205.f
));
865 EmulateDrawingOneFrame(root
.get());
867 child1
->render_surface()->damage_tracker()->current_damage_rect();
869 root
->render_surface()->damage_tracker()->current_damage_rect();
871 // The new surface bounds should be damaged entirely, even though only one of
872 // the layers changed.
873 EXPECT_EQ(gfx::Rect(190, 190, 11, 23).ToString(),
874 child_damage_rect
.ToString());
876 // Damage to the root surface should be the union of child1's *entire* render
877 // surface (in target space), and its old exposed area (also in target
879 EXPECT_EQ(gfx::Rect(290, 290, 16, 23).ToString(),
880 root_damage_rect
.ToString());
883 TEST_F(DamageTrackerTest
, VerifyDamageForSurfaceChangeFromAncestorLayer
) {
884 // An ancestor/owning layer changes that affects the position/transform of
885 // the render surface. Note that in this case, the layer_property_changed flag
886 // already propagates to the subtree (tested in LayerImpltest), which damages
887 // the entire child1 surface, but the damage tracker still needs the correct
888 // logic to compute the exposed region on the root surface.
890 // TODO(shawnsingh): the expectations of this test case should change when we
891 // add support for a unique scissor_rect per RenderSurface. In that case, the
892 // child1 surface should be completely unchanged, since we are only
893 // transforming it, while the root surface would be damaged appropriately.
895 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithTwoSurfaces();
896 LayerImpl
* child1
= root
->children()[0];
897 gfx::Rect child_damage_rect
;
898 gfx::Rect root_damage_rect
;
900 ClearDamageForAllSurfaces(root
.get());
901 child1
->SetPosition(gfx::PointF(50.f
, 50.f
));
902 EmulateDrawingOneFrame(root
.get());
904 child1
->render_surface()->damage_tracker()->current_damage_rect();
906 root
->render_surface()->damage_tracker()->current_damage_rect();
908 // The new surface bounds should be damaged entirely.
909 EXPECT_EQ(gfx::Rect(190, 190, 16, 18).ToString(),
910 child_damage_rect
.ToString());
912 // The entire child1 surface and the old exposed child1 surface should damage
914 // - old child1 surface in target space: gfx::Rect(290, 290, 16, 18)
915 // - new child1 surface in target space: gfx::Rect(240, 240, 16, 18)
916 EXPECT_EQ(gfx::Rect(240, 240, 66, 68).ToString(),
917 root_damage_rect
.ToString());
920 TEST_F(DamageTrackerTest
, VerifyDamageForAddingAndRemovingRenderSurfaces
) {
921 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithTwoSurfaces();
922 LayerImpl
* child1
= root
->children()[0];
923 gfx::Rect child_damage_rect
;
924 gfx::Rect root_damage_rect
;
926 // CASE 1: If a descendant surface disappears, its entire old area becomes
928 ClearDamageForAllSurfaces(root
.get());
929 child1
->SetOpacity(1.f
);
930 child1
->SetForceRenderSurface(false);
931 EmulateDrawingOneFrame(root
.get());
933 // Sanity check that there is only one surface now.
934 ASSERT_FALSE(child1
->render_surface());
935 ASSERT_EQ(4u, root
->render_surface()->layer_list().size());
938 root
->render_surface()->damage_tracker()->current_damage_rect();
939 EXPECT_EQ(gfx::Rect(290, 290, 16, 18).ToString(),
940 root_damage_rect
.ToString());
942 // CASE 2: If a descendant surface appears, its entire old area becomes
945 // Cycle one frame of no change, just to sanity check that the next rect is
946 // not because of the old damage state.
947 ClearDamageForAllSurfaces(root
.get());
948 EmulateDrawingOneFrame(root
.get());
950 root
->render_surface()->damage_tracker()->current_damage_rect();
951 EXPECT_TRUE(root_damage_rect
.IsEmpty());
953 // Then change the tree so that the render surface is added back.
954 ClearDamageForAllSurfaces(root
.get());
955 child1
->SetOpacity(0.5f
);
956 child1
->SetForceRenderSurface(true);
957 EmulateDrawingOneFrame(root
.get());
959 // Sanity check that there is a new surface now.
960 ASSERT_TRUE(child1
->render_surface());
961 EXPECT_EQ(3u, root
->render_surface()->layer_list().size());
962 EXPECT_EQ(2u, child1
->render_surface()->layer_list().size());
965 child1
->render_surface()->damage_tracker()->current_damage_rect();
967 root
->render_surface()->damage_tracker()->current_damage_rect();
968 EXPECT_EQ(gfx::Rect(190, 190, 16, 18).ToString(),
969 child_damage_rect
.ToString());
970 EXPECT_EQ(gfx::Rect(290, 290, 16, 18).ToString(),
971 root_damage_rect
.ToString());
974 TEST_F(DamageTrackerTest
, VerifyNoDamageWhenNothingChanged
) {
975 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithTwoSurfaces();
976 LayerImpl
* child1
= root
->children()[0];
977 gfx::Rect child_damage_rect
;
978 gfx::Rect root_damage_rect
;
980 // CASE 1: If nothing changes, the damage rect should be empty.
982 ClearDamageForAllSurfaces(root
.get());
983 EmulateDrawingOneFrame(root
.get());
985 child1
->render_surface()->damage_tracker()->current_damage_rect();
987 root
->render_surface()->damage_tracker()->current_damage_rect();
988 EXPECT_TRUE(child_damage_rect
.IsEmpty());
989 EXPECT_TRUE(root_damage_rect
.IsEmpty());
991 // CASE 2: If nothing changes twice in a row, the damage rect should still be
994 ClearDamageForAllSurfaces(root
.get());
995 EmulateDrawingOneFrame(root
.get());
997 child1
->render_surface()->damage_tracker()->current_damage_rect();
999 root
->render_surface()->damage_tracker()->current_damage_rect();
1000 EXPECT_TRUE(child_damage_rect
.IsEmpty());
1001 EXPECT_TRUE(root_damage_rect
.IsEmpty());
1004 TEST_F(DamageTrackerTest
, VerifyNoDamageForUpdateRectThatDoesNotDrawContent
) {
1005 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithTwoSurfaces();
1006 LayerImpl
* child1
= root
->children()[0];
1007 gfx::Rect child_damage_rect
;
1008 gfx::Rect root_damage_rect
;
1010 // In our specific tree, the update rect of child1 should not cause any
1011 // damage to any surface because it does not actually draw content.
1012 ClearDamageForAllSurfaces(root
.get());
1013 child1
->SetUpdateRect(gfx::Rect(1, 2));
1014 EmulateDrawingOneFrame(root
.get());
1016 child1
->render_surface()->damage_tracker()->current_damage_rect();
1018 root
->render_surface()->damage_tracker()->current_damage_rect();
1019 EXPECT_TRUE(child_damage_rect
.IsEmpty());
1020 EXPECT_TRUE(root_damage_rect
.IsEmpty());
1023 TEST_F(DamageTrackerTest
, VerifyDamageForReplica
) {
1024 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithTwoSurfaces();
1025 LayerImpl
* child1
= root
->children()[0];
1026 LayerImpl
* grand_child1
= child1
->children()[0];
1027 LayerImpl
* grand_child2
= child1
->children()[1];
1029 // Damage on a surface that has a reflection should cause the target surface
1030 // to receive the surface's damage and the surface's reflected damage.
1032 // For this test case, we modify grand_child2, and add grand_child3 to extend
1033 // the bounds of child1's surface. This way, we can test reflection changes
1034 // without changing content_bounds of the surface.
1035 grand_child2
->SetPosition(gfx::PointF(180.f
, 180.f
));
1037 scoped_ptr
<LayerImpl
> grand_child3
=
1038 LayerImpl::Create(host_impl_
.active_tree(), 6);
1039 grand_child3
->SetPosition(gfx::PointF(240.f
, 240.f
));
1040 grand_child3
->SetBounds(gfx::Size(10, 10));
1041 grand_child3
->SetContentBounds(gfx::Size(10, 10));
1042 grand_child3
->SetDrawsContent(true);
1043 child1
->AddChild(grand_child3
.Pass());
1045 child1
->SetOpacity(0.5f
);
1046 EmulateDrawingOneFrame(root
.get());
1048 // CASE 1: adding a reflection about the left edge of grand_child1.
1050 ClearDamageForAllSurfaces(root
.get());
1052 scoped_ptr
<LayerImpl
> grand_child1_replica
=
1053 LayerImpl::Create(host_impl_
.active_tree(), 7);
1054 grand_child1_replica
->SetPosition(gfx::PointF());
1055 gfx::Transform reflection
;
1056 reflection
.Scale3d(-1.0, 1.0, 1.0);
1057 grand_child1_replica
->SetTransform(reflection
);
1058 grand_child1
->SetReplicaLayer(grand_child1_replica
.Pass());
1060 EmulateDrawingOneFrame(root
.get());
1062 gfx::Rect grand_child_damage_rect
=
1063 grand_child1
->render_surface()->damage_tracker()->current_damage_rect();
1064 gfx::Rect child_damage_rect
=
1065 child1
->render_surface()->damage_tracker()->current_damage_rect();
1066 gfx::Rect root_damage_rect
=
1067 root
->render_surface()->damage_tracker()->current_damage_rect();
1069 // The grand_child surface damage should not include its own replica. The
1070 // child surface damage should include the normal and replica surfaces.
1071 EXPECT_EQ(gfx::Rect(6, 8).ToString(), grand_child_damage_rect
.ToString());
1072 EXPECT_EQ(gfx::Rect(194, 200, 12, 8).ToString(),
1073 child_damage_rect
.ToString());
1074 EXPECT_EQ(gfx::Rect(294, 300, 12, 8).ToString(), root_damage_rect
.ToString());
1076 // CASE 2: moving the descendant surface should cause both the original and
1077 // reflected areas to be damaged on the target.
1078 ClearDamageForAllSurfaces(root
.get());
1079 gfx::Rect old_content_rect
= child1
->render_surface()->content_rect();
1080 grand_child1
->SetPosition(gfx::PointF(195.f
, 205.f
));
1081 EmulateDrawingOneFrame(root
.get());
1082 ASSERT_EQ(old_content_rect
.width(),
1083 child1
->render_surface()->content_rect().width());
1084 ASSERT_EQ(old_content_rect
.height(),
1085 child1
->render_surface()->content_rect().height());
1087 grand_child_damage_rect
=
1088 grand_child1
->render_surface()->
1089 damage_tracker()->current_damage_rect();
1091 child1
->render_surface()->damage_tracker()->current_damage_rect();
1093 root
->render_surface()->damage_tracker()->current_damage_rect();
1095 // The child surface damage should include normal and replica surfaces for
1096 // both old and new locations.
1097 // - old location in target space: gfx::Rect(194, 200, 12, 8)
1098 // - new location in target space: gfx::Rect(189, 205, 12, 8)
1099 EXPECT_EQ(gfx::Rect(6, 8).ToString(), grand_child_damage_rect
.ToString());
1100 EXPECT_EQ(gfx::Rect(189, 200, 17, 13).ToString(),
1101 child_damage_rect
.ToString());
1102 EXPECT_EQ(gfx::Rect(289, 300, 17, 13).ToString(),
1103 root_damage_rect
.ToString());
1105 // CASE 3: removing the reflection should cause the entire region including
1106 // reflection to damage the target surface.
1107 ClearDamageForAllSurfaces(root
.get());
1108 grand_child1
->SetReplicaLayer(nullptr);
1109 EmulateDrawingOneFrame(root
.get());
1110 ASSERT_EQ(old_content_rect
.width(),
1111 child1
->render_surface()->content_rect().width());
1112 ASSERT_EQ(old_content_rect
.height(),
1113 child1
->render_surface()->content_rect().height());
1115 EXPECT_FALSE(grand_child1
->render_surface());
1117 child1
->render_surface()->damage_tracker()->current_damage_rect();
1119 root
->render_surface()->damage_tracker()->current_damage_rect();
1121 EXPECT_EQ(gfx::Rect(189, 205, 12, 8).ToString(),
1122 child_damage_rect
.ToString());
1123 EXPECT_EQ(gfx::Rect(289, 305, 12, 8).ToString(), root_damage_rect
.ToString());
1126 TEST_F(DamageTrackerTest
, VerifyDamageForMask
) {
1127 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
1128 LayerImpl
* child
= root
->children()[0];
1130 // In the current implementation of the damage tracker, changes to mask
1131 // layers should damage the entire corresponding surface.
1133 ClearDamageForAllSurfaces(root
.get());
1135 // Set up the mask layer.
1137 scoped_ptr
<LayerImpl
> mask_layer
=
1138 LayerImpl::Create(host_impl_
.active_tree(), 3);
1139 mask_layer
->SetPosition(child
->position());
1140 mask_layer
->SetBounds(child
->bounds());
1141 mask_layer
->SetContentBounds(child
->bounds());
1142 child
->SetMaskLayer(mask_layer
.Pass());
1144 LayerImpl
* mask_layer
= child
->mask_layer();
1146 // Add opacity and a grand_child so that the render surface persists even
1147 // after we remove the mask.
1148 child
->SetOpacity(0.5f
);
1150 scoped_ptr
<LayerImpl
> grand_child
=
1151 LayerImpl::Create(host_impl_
.active_tree(), 4);
1152 grand_child
->SetPosition(gfx::PointF(2.f
, 2.f
));
1153 grand_child
->SetBounds(gfx::Size(2, 2));
1154 grand_child
->SetContentBounds(gfx::Size(2, 2));
1155 grand_child
->SetDrawsContent(true);
1156 child
->AddChild(grand_child
.Pass());
1158 EmulateDrawingOneFrame(root
.get());
1160 // Sanity check that a new surface was created for the child.
1161 ASSERT_TRUE(child
->render_surface());
1163 // CASE 1: the update_rect on a mask layer should damage the entire target
1165 ClearDamageForAllSurfaces(root
.get());
1166 mask_layer
->SetUpdateRect(gfx::Rect(1, 2, 3, 4));
1167 EmulateDrawingOneFrame(root
.get());
1168 gfx::Rect child_damage_rect
=
1169 child
->render_surface()->damage_tracker()->current_damage_rect();
1170 EXPECT_EQ(gfx::Rect(30, 30).ToString(), child_damage_rect
.ToString());
1172 // CASE 2: a property change on the mask layer should damage the entire
1175 // Advance one frame without damage so that we know the damage rect is not
1176 // leftover from the previous case.
1177 ClearDamageForAllSurfaces(root
.get());
1178 EmulateDrawingOneFrame(root
.get());
1180 child
->render_surface()->damage_tracker()->current_damage_rect();
1181 EXPECT_TRUE(child_damage_rect
.IsEmpty());
1183 // Then test the property change.
1184 ClearDamageForAllSurfaces(root
.get());
1185 mask_layer
->SetStackingOrderChanged(true);
1187 EmulateDrawingOneFrame(root
.get());
1189 child
->render_surface()->damage_tracker()->current_damage_rect();
1190 EXPECT_EQ(gfx::Rect(30, 30).ToString(), child_damage_rect
.ToString());
1192 // CASE 3: removing the mask also damages the entire target surface.
1195 // Advance one frame without damage so that we know the damage rect is not
1196 // leftover from the previous case.
1197 ClearDamageForAllSurfaces(root
.get());
1198 EmulateDrawingOneFrame(root
.get());
1200 child
->render_surface()->damage_tracker()->current_damage_rect();
1201 EXPECT_TRUE(child_damage_rect
.IsEmpty());
1203 // Then test mask removal.
1204 ClearDamageForAllSurfaces(root
.get());
1205 child
->SetMaskLayer(nullptr);
1206 ASSERT_TRUE(child
->LayerPropertyChanged());
1207 EmulateDrawingOneFrame(root
.get());
1209 // Sanity check that a render surface still exists.
1210 ASSERT_TRUE(child
->render_surface());
1213 child
->render_surface()->damage_tracker()->current_damage_rect();
1214 EXPECT_EQ(gfx::Rect(30, 30).ToString(), child_damage_rect
.ToString());
1217 TEST_F(DamageTrackerTest
, VerifyDamageForReplicaMask
) {
1218 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithTwoSurfaces();
1219 LayerImpl
* child1
= root
->children()[0];
1220 LayerImpl
* grand_child1
= child1
->children()[0];
1222 // Changes to a replica's mask should not damage the original surface,
1223 // because it is not masked. But it does damage the ancestor target surface.
1225 ClearDamageForAllSurfaces(root
.get());
1227 // Create a reflection about the left edge of grand_child1.
1229 scoped_ptr
<LayerImpl
> grand_child1_replica
=
1230 LayerImpl::Create(host_impl_
.active_tree(), 6);
1231 grand_child1_replica
->SetPosition(gfx::PointF());
1232 gfx::Transform reflection
;
1233 reflection
.Scale3d(-1.0, 1.0, 1.0);
1234 grand_child1_replica
->SetTransform(reflection
);
1235 grand_child1
->SetReplicaLayer(grand_child1_replica
.Pass());
1237 LayerImpl
* grand_child1_replica
= grand_child1
->replica_layer();
1239 // Set up the mask layer on the replica layer
1241 scoped_ptr
<LayerImpl
> replica_mask_layer
=
1242 LayerImpl::Create(host_impl_
.active_tree(), 7);
1243 replica_mask_layer
->SetPosition(gfx::PointF());
1244 replica_mask_layer
->SetBounds(grand_child1
->bounds());
1245 replica_mask_layer
->SetContentBounds(grand_child1
->bounds());
1246 grand_child1_replica
->SetMaskLayer(replica_mask_layer
.Pass());
1248 LayerImpl
* replica_mask_layer
= grand_child1_replica
->mask_layer();
1250 EmulateDrawingOneFrame(root
.get());
1252 // Sanity check that the appropriate render surfaces were created
1253 ASSERT_TRUE(grand_child1
->render_surface());
1255 // CASE 1: a property change on the mask should damage only the reflected
1256 // region on the target surface.
1257 ClearDamageForAllSurfaces(root
.get());
1258 replica_mask_layer
->SetStackingOrderChanged(true);
1259 EmulateDrawingOneFrame(root
.get());
1261 gfx::Rect grand_child_damage_rect
=
1262 grand_child1
->render_surface()->damage_tracker()->current_damage_rect();
1263 gfx::Rect child_damage_rect
=
1264 child1
->render_surface()->damage_tracker()->current_damage_rect();
1266 EXPECT_TRUE(grand_child_damage_rect
.IsEmpty());
1267 EXPECT_EQ(gfx::Rect(194, 200, 6, 8).ToString(), child_damage_rect
.ToString());
1269 // CASE 2: removing the replica mask damages only the reflected region on the
1272 ClearDamageForAllSurfaces(root
.get());
1273 grand_child1_replica
->SetMaskLayer(nullptr);
1274 EmulateDrawingOneFrame(root
.get());
1276 grand_child_damage_rect
=
1277 grand_child1
->render_surface()->damage_tracker()->
1278 current_damage_rect();
1280 child1
->render_surface()->damage_tracker()->current_damage_rect();
1282 EXPECT_TRUE(grand_child_damage_rect
.IsEmpty());
1283 EXPECT_EQ(gfx::Rect(194, 200, 6, 8).ToString(), child_damage_rect
.ToString());
1286 TEST_F(DamageTrackerTest
, VerifyDamageForReplicaMaskWithTransformOrigin
) {
1287 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithTwoSurfaces();
1288 LayerImpl
* child1
= root
->children()[0];
1289 LayerImpl
* grand_child1
= child1
->children()[0];
1291 // Verify that the correct replica_origin_transform is used for the
1293 ClearDamageForAllSurfaces(root
.get());
1295 // This is not actually the transform origin point being tested, but by
1297 // expected to be the same as the replica's anchor point.
1298 grand_child1
->SetTransformOrigin(
1299 gfx::Point3F(grand_child1
->bounds().width(), 0.f
, 0.f
));
1302 scoped_ptr
<LayerImpl
> grand_child1_replica
=
1303 LayerImpl::Create(host_impl_
.active_tree(), 6);
1304 grand_child1_replica
->SetPosition(gfx::PointF());
1306 // This is the anchor being tested.
1307 grand_child1_replica
->SetTransformOrigin(
1308 gfx::Point3F(grand_child1
->bounds().width(), 0.f
, 0.f
));
1309 gfx::Transform reflection
;
1310 reflection
.Scale3d(-1.0, 1.0, 1.0);
1311 grand_child1_replica
->SetTransform(reflection
);
1312 grand_child1
->SetReplicaLayer(grand_child1_replica
.Pass());
1314 LayerImpl
* grand_child1_replica
= grand_child1
->replica_layer();
1316 // Set up the mask layer on the replica layer
1318 scoped_ptr
<LayerImpl
> replica_mask_layer
=
1319 LayerImpl::Create(host_impl_
.active_tree(), 7);
1320 replica_mask_layer
->SetPosition(gfx::PointF());
1321 // Note: this is not the transform origin being tested.
1322 replica_mask_layer
->SetBounds(grand_child1
->bounds());
1323 replica_mask_layer
->SetContentBounds(grand_child1
->bounds());
1324 grand_child1_replica
->SetMaskLayer(replica_mask_layer
.Pass());
1326 LayerImpl
* replica_mask_layer
= grand_child1_replica
->mask_layer();
1328 EmulateDrawingOneFrame(root
.get());
1330 // Sanity check that the appropriate render surfaces were created
1331 ASSERT_TRUE(grand_child1
->render_surface());
1333 // A property change on the replica_mask should damage the reflected region on
1334 // the target surface.
1335 ClearDamageForAllSurfaces(root
.get());
1336 replica_mask_layer
->SetStackingOrderChanged(true);
1338 EmulateDrawingOneFrame(root
.get());
1340 gfx::Rect child_damage_rect
=
1341 child1
->render_surface()->damage_tracker()->current_damage_rect();
1342 EXPECT_EQ(gfx::Rect(206, 200, 6, 8).ToString(), child_damage_rect
.ToString());
1345 TEST_F(DamageTrackerTest
, DamageWhenAddedExternally
) {
1346 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
1347 LayerImpl
* child
= root
->children()[0];
1349 // Case 1: This test ensures that when the tracker is given damage, that
1350 // it is included with any other partial damage.
1352 ClearDamageForAllSurfaces(root
.get());
1353 child
->SetUpdateRect(gfx::Rect(10, 11, 12, 13));
1354 root
->render_surface()->damage_tracker()->AddDamageNextUpdate(
1355 gfx::Rect(15, 16, 32, 33));
1356 EmulateDrawingOneFrame(root
.get());
1357 gfx::Rect root_damage_rect
=
1358 root
->render_surface()->damage_tracker()->current_damage_rect();
1359 EXPECT_EQ(gfx::UnionRects(gfx::Rect(15, 16, 32, 33),
1360 gfx::Rect(100 + 10, 100 + 11, 12, 13)).ToString(),
1361 root_damage_rect
.ToString());
1363 // Case 2: An additional sanity check that adding damage works even when
1364 // nothing on the layer tree changed.
1366 ClearDamageForAllSurfaces(root
.get());
1367 root
->render_surface()->damage_tracker()->AddDamageNextUpdate(
1368 gfx::Rect(30, 31, 14, 15));
1369 EmulateDrawingOneFrame(root
.get());
1371 root
->render_surface()->damage_tracker()->current_damage_rect();
1372 EXPECT_EQ(gfx::Rect(30, 31, 14, 15).ToString(), root_damage_rect
.ToString());
1375 TEST_F(DamageTrackerTest
, VerifyDamageForEmptyLayerList
) {
1376 // Though it should never happen, its a good idea to verify that the damage
1377 // tracker does not crash when it receives an empty layer_list.
1379 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
.active_tree(), 1);
1380 root
->CreateRenderSurface();
1382 ASSERT_TRUE(root
== root
->render_target());
1383 RenderSurfaceImpl
* target_surface
= root
->render_surface();
1385 LayerImplList empty_list
;
1386 target_surface
->damage_tracker()->UpdateDamageTrackingState(
1388 target_surface
->OwningLayerId(),
1392 FilterOperations());
1394 gfx::Rect damage_rect
=
1395 target_surface
->damage_tracker()->current_damage_rect();
1396 EXPECT_TRUE(damage_rect
.IsEmpty());
1399 TEST_F(DamageTrackerTest
, VerifyDamageAccumulatesUntilReset
) {
1400 // If damage is not cleared, it should accumulate.
1402 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
1403 LayerImpl
* child
= root
->children()[0];
1405 ClearDamageForAllSurfaces(root
.get());
1406 child
->SetUpdateRect(gfx::Rect(10.f
, 11.f
, 1.f
, 2.f
));
1407 EmulateDrawingOneFrame(root
.get());
1409 // Sanity check damage after the first frame; this isnt the actual test yet.
1410 gfx::Rect root_damage_rect
=
1411 root
->render_surface()->damage_tracker()->current_damage_rect();
1412 EXPECT_EQ(gfx::Rect(110, 111, 1, 2).ToString(), root_damage_rect
.ToString());
1414 // New damage, without having cleared the previous damage, should be unioned
1415 // to the previous one.
1416 child
->SetUpdateRect(gfx::Rect(20, 25, 1, 2));
1417 EmulateDrawingOneFrame(root
.get());
1419 root
->render_surface()->damage_tracker()->current_damage_rect();
1420 EXPECT_EQ(gfx::Rect(110, 111, 11, 16).ToString(),
1421 root_damage_rect
.ToString());
1423 // If we notify the damage tracker that we drew the damaged area, then damage
1424 // should be emptied.
1425 root
->render_surface()->damage_tracker()->DidDrawDamagedArea();
1427 root
->render_surface()->damage_tracker()->current_damage_rect();
1428 EXPECT_TRUE(root_damage_rect
.IsEmpty());
1430 // Damage should remain empty even after one frame, since there's yet no new
1432 EmulateDrawingOneFrame(root
.get());
1434 root
->render_surface()->damage_tracker()->current_damage_rect();
1435 EXPECT_TRUE(root_damage_rect
.IsEmpty());
1438 TEST_F(DamageTrackerTest
, HugeDamageRect
) {
1439 // This number is so large that we start losting floating point accuracy.
1440 const int kBigNumber
= 900000000;
1441 // Walk over a range to find floating point inaccuracy boundaries that move
1442 // toward the wrong direction.
1443 const int kRange
= 5000;
1445 for (int i
= 0; i
< kRange
; ++i
) {
1446 scoped_ptr
<LayerImpl
> root
= CreateTestTreeWithOneSurface();
1447 LayerImpl
* child
= root
->children()[0];
1449 gfx::Transform transform
;
1450 transform
.Translate(-kBigNumber
, -kBigNumber
);
1452 // The child layer covers (0, 0, i, i) of the viewport,
1453 // but has a huge negative position.
1454 child
->SetPosition(gfx::PointF());
1455 child
->SetBounds(gfx::Size(kBigNumber
+ i
, kBigNumber
+ i
));
1456 child
->SetContentBounds(gfx::Size(kBigNumber
+ i
, kBigNumber
+ i
));
1457 child
->SetTransform(transform
);
1458 EmulateDrawingOneFrame(root
.get());
1460 // The expected damage should cover the visible part of the child layer,
1461 // which is (0, 0, i, i) in the viewport.
1462 gfx::Rect root_damage_rect
=
1463 root
->render_surface()->damage_tracker()->current_damage_rect();
1464 gfx::Rect damage_we_care_about
= gfx::Rect(i
, i
);
1465 EXPECT_LE(damage_we_care_about
.right(), root_damage_rect
.right());
1466 EXPECT_LE(damage_we_care_about
.bottom(), root_damage_rect
.bottom());