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 LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting
inputs(
34 root
, root
->bounds(), render_surface_layer_list
);
35 LayerTreeHostCommon::CalculateDrawProperties(&inputs
);
38 void ClearDamageForAllSurfaces(LayerImpl
* layer
) {
39 if (layer
->render_surface())
40 layer
->render_surface()->damage_tracker()->DidDrawDamagedArea();
42 // Recursively clear damage for any existing surface.
43 for (size_t i
= 0; i
< layer
->children().size(); ++i
)
44 ClearDamageForAllSurfaces(layer
->children()[i
]);
47 void EmulateDrawingOneFrame(LayerImpl
* root
) {
48 // This emulates only steps that are relevant to testing the damage tracker:
49 // 1. computing the render passes and layerlists
50 // 2. updating all damage trackers in the correct order
51 // 3. resetting all update_rects and property_changed flags for all layers
54 LayerImplList render_surface_layer_list
;
55 ExecuteCalculateDrawProperties(root
, &render_surface_layer_list
);
57 // Iterate back-to-front, so that damage correctly propagates from descendant
58 // surfaces to ancestors.
59 for (int i
= render_surface_layer_list
.size() - 1; i
>= 0; --i
) {
60 RenderSurfaceImpl
* target_surface
=
61 render_surface_layer_list
[i
]->render_surface();
62 target_surface
->damage_tracker()->UpdateDamageTrackingState(
63 target_surface
->layer_list(),
64 target_surface
->OwningLayerId(),
65 target_surface
->SurfacePropertyChangedOnlyFromDescendant(),
66 target_surface
->content_rect(),
67 render_surface_layer_list
[i
]->mask_layer(),
68 render_surface_layer_list
[i
]->filters());
71 root
->ResetAllChangeTrackingForSubtree();
74 class DamageTrackerTest
: public testing::Test
{
76 DamageTrackerTest() : host_impl_(&proxy_
, &shared_bitmap_manager_
) {}
78 scoped_ptr
<LayerImpl
> CreateTestTreeWithOneSurface() {
79 scoped_ptr
<LayerImpl
> root
=
80 LayerImpl::Create(host_impl_
.active_tree(), 1);
81 scoped_ptr
<LayerImpl
> child
=
82 LayerImpl::Create(host_impl_
.active_tree(), 2);
84 root
->SetPosition(gfx::PointF());
85 root
->SetBounds(gfx::Size(500, 500));
86 root
->SetContentBounds(gfx::Size(500, 500));
87 root
->SetDrawsContent(true);
88 root
->CreateRenderSurface();
89 root
->render_surface()->SetContentRect(gfx::Rect(0, 0, 500, 500));
91 child
->SetPosition(gfx::PointF(100.f
, 100.f
));
92 child
->SetBounds(gfx::Size(30, 30));
93 child
->SetContentBounds(gfx::Size(30, 30));
94 child
->SetDrawsContent(true);
95 root
->AddChild(child
.Pass());
100 scoped_ptr
<LayerImpl
> CreateTestTreeWithTwoSurfaces() {
101 // This test tree has two render surfaces: one for the root, and one for
102 // child1. Additionally, the root has a second child layer, and child1 has
103 // two children of its own.
105 scoped_ptr
<LayerImpl
> root
=
106 LayerImpl::Create(host_impl_
.active_tree(), 1);
107 scoped_ptr
<LayerImpl
> child1
=
108 LayerImpl::Create(host_impl_
.active_tree(), 2);
109 scoped_ptr
<LayerImpl
> child2
=
110 LayerImpl::Create(host_impl_
.active_tree(), 3);
111 scoped_ptr
<LayerImpl
> grand_child1
=
112 LayerImpl::Create(host_impl_
.active_tree(), 4);
113 scoped_ptr
<LayerImpl
> grand_child2
=
114 LayerImpl::Create(host_impl_
.active_tree(), 5);
116 root
->SetPosition(gfx::PointF());
117 root
->SetBounds(gfx::Size(500, 500));
118 root
->SetContentBounds(gfx::Size(500, 500));
119 root
->SetDrawsContent(true);
120 root
->CreateRenderSurface();
121 root
->render_surface()->SetContentRect(gfx::Rect(0, 0, 500, 500));
123 child1
->SetPosition(gfx::PointF(100.f
, 100.f
));
124 child1
->SetBounds(gfx::Size(30, 30));
125 child1
->SetContentBounds(gfx::Size(30, 30));
126 // With a child that draws_content, opacity will cause the layer to create
127 // its own RenderSurface. This layer does not draw, but is intended to
128 // create its own RenderSurface. TODO: setting opacity and
129 // ForceRenderSurface may be redundant here.
130 child1
->SetOpacity(0.5f
);
131 child1
->SetDrawsContent(false);
132 child1
->SetForceRenderSurface(true);
134 child2
->SetPosition(gfx::PointF(11.f
, 11.f
));
135 child2
->SetBounds(gfx::Size(18, 18));
136 child2
->SetContentBounds(gfx::Size(18, 18));
137 child2
->SetDrawsContent(true);
139 grand_child1
->SetPosition(gfx::PointF(200.f
, 200.f
));
140 grand_child1
->SetBounds(gfx::Size(6, 8));
141 grand_child1
->SetContentBounds(gfx::Size(6, 8));
142 grand_child1
->SetDrawsContent(true);
144 grand_child2
->SetPosition(gfx::PointF(190.f
, 190.f
));
145 grand_child2
->SetBounds(gfx::Size(6, 8));
146 grand_child2
->SetContentBounds(gfx::Size(6, 8));
147 grand_child2
->SetDrawsContent(true);
149 child1
->AddChild(grand_child1
.Pass());
150 child1
->AddChild(grand_child2
.Pass());
151 root
->AddChild(child1
.Pass());
152 root
->AddChild(child2
.Pass());
157 scoped_ptr
<LayerImpl
> CreateAndSetUpTestTreeWithOneSurface() {
158 scoped_ptr
<LayerImpl
> root
= CreateTestTreeWithOneSurface();
160 // Setup includes going past the first frame which always damages
161 // everything, so that we can actually perform specific tests.
162 EmulateDrawingOneFrame(root
.get());
167 scoped_ptr
<LayerImpl
> CreateAndSetUpTestTreeWithTwoSurfaces() {
168 scoped_ptr
<LayerImpl
> root
= CreateTestTreeWithTwoSurfaces();
170 // Setup includes going past the first frame which always damages
171 // everything, so that we can actually perform specific tests.
172 EmulateDrawingOneFrame(root
.get());
178 FakeImplProxy proxy_
;
179 TestSharedBitmapManager shared_bitmap_manager_
;
180 FakeLayerTreeHostImpl host_impl_
;
183 TEST_F(DamageTrackerTest
, SanityCheckTestTreeWithOneSurface
) {
184 // Sanity check that the simple test tree will actually produce the expected
185 // render surfaces and layer lists.
187 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
189 EXPECT_EQ(2u, root
->render_surface()->layer_list().size());
190 EXPECT_EQ(1, root
->render_surface()->layer_list()[0]->id());
191 EXPECT_EQ(2, root
->render_surface()->layer_list()[1]->id());
193 gfx::Rect root_damage_rect
=
194 root
->render_surface()->damage_tracker()->current_damage_rect();
196 EXPECT_EQ(gfx::Rect(500, 500).ToString(), root_damage_rect
.ToString());
199 TEST_F(DamageTrackerTest
, SanityCheckTestTreeWithTwoSurfaces
) {
200 // Sanity check that the complex test tree will actually produce the expected
201 // render surfaces and layer lists.
203 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithTwoSurfaces();
205 LayerImpl
* child1
= root
->children()[0];
206 LayerImpl
* child2
= root
->children()[1];
207 gfx::Rect child_damage_rect
=
208 child1
->render_surface()->damage_tracker()->current_damage_rect();
209 gfx::Rect root_damage_rect
=
210 root
->render_surface()->damage_tracker()->current_damage_rect();
212 ASSERT_TRUE(child1
->render_surface());
213 EXPECT_FALSE(child2
->render_surface());
214 EXPECT_EQ(3u, root
->render_surface()->layer_list().size());
215 EXPECT_EQ(2u, child1
->render_surface()->layer_list().size());
217 // The render surface for child1 only has a content_rect that encloses
218 // grand_child1 and grand_child2, because child1 does not draw content.
219 EXPECT_EQ(gfx::Rect(190, 190, 16, 18).ToString(),
220 child_damage_rect
.ToString());
221 EXPECT_EQ(gfx::Rect(500, 500).ToString(), root_damage_rect
.ToString());
224 TEST_F(DamageTrackerTest
, VerifyDamageForUpdateRects
) {
225 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
226 LayerImpl
* child
= root
->children()[0];
228 // CASE 1: Setting the update rect should cause the corresponding damage to
230 ClearDamageForAllSurfaces(root
.get());
231 child
->SetUpdateRect(gfx::RectF(10.f
, 11.f
, 12.f
, 13.f
));
232 EmulateDrawingOneFrame(root
.get());
234 // Damage position on the surface should be: position of update_rect (10, 11)
235 // relative to the child (100, 100).
236 gfx::Rect root_damage_rect
=
237 root
->render_surface()->damage_tracker()->current_damage_rect();
238 EXPECT_EQ(gfx::Rect(110, 111, 12, 13).ToString(),
239 root_damage_rect
.ToString());
241 // CASE 2: The same update rect twice in a row still produces the same
243 ClearDamageForAllSurfaces(root
.get());
244 child
->SetUpdateRect(gfx::RectF(10.f
, 11.f
, 12.f
, 13.f
));
245 EmulateDrawingOneFrame(root
.get());
247 root
->render_surface()->damage_tracker()->current_damage_rect();
248 EXPECT_EQ(gfx::Rect(110, 111, 12, 13).ToString(),
249 root_damage_rect
.ToString());
251 // CASE 3: Setting a different update rect should cause damage on the new
252 // update region, but no additional exposed old region.
253 ClearDamageForAllSurfaces(root
.get());
254 child
->SetUpdateRect(gfx::RectF(20.f
, 25.f
, 1.f
, 2.f
));
255 EmulateDrawingOneFrame(root
.get());
257 // Damage position on the surface should be: position of update_rect (20, 25)
258 // relative to the child (100, 100).
260 root
->render_surface()->damage_tracker()->current_damage_rect();
261 EXPECT_EQ(gfx::Rect(120, 125, 1, 2).ToString(), root_damage_rect
.ToString());
264 TEST_F(DamageTrackerTest
, VerifyDamageForLayerDamageRects
) {
265 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
266 LayerImpl
* child
= root
->children()[0];
268 // CASE 1: Adding the layer damage rect should cause the corresponding damage
270 ClearDamageForAllSurfaces(root
.get());
271 child
->AddDamageRect(gfx::RectF(10.f
, 11.f
, 12.f
, 13.f
));
272 EmulateDrawingOneFrame(root
.get());
274 // Damage position on the surface should be: position of layer damage_rect
275 // (10, 11) relative to the child (100, 100).
276 gfx::Rect root_damage_rect
=
277 root
->render_surface()->damage_tracker()->current_damage_rect();
278 EXPECT_EQ(true, root_damage_rect
.Contains(gfx::Rect(110, 111, 12, 13)));
280 // CASE 2: The same layer damage rect twice in a row still produces the same
282 ClearDamageForAllSurfaces(root
.get());
283 child
->AddDamageRect(gfx::RectF(10.f
, 11.f
, 12.f
, 13.f
));
284 EmulateDrawingOneFrame(root
.get());
286 root
->render_surface()->damage_tracker()->current_damage_rect();
287 EXPECT_EQ(true, root_damage_rect
.Contains(gfx::Rect(110, 111, 12, 13)));
289 // CASE 3: Adding a different layer damage rect should cause damage on the
290 // new damaged region, but no additional exposed old region.
291 ClearDamageForAllSurfaces(root
.get());
292 child
->AddDamageRect(gfx::RectF(20.f
, 25.f
, 1.f
, 2.f
));
293 EmulateDrawingOneFrame(root
.get());
295 // Damage position on the surface should be: position of layer damage_rect
296 // (20, 25) relative to the child (100, 100).
298 root
->render_surface()->damage_tracker()->current_damage_rect();
299 EXPECT_EQ(true, root_damage_rect
.Contains(gfx::Rect(120, 125, 1, 2)));
301 // CASE 4: Adding multiple layer damage rects should cause a unified
302 // damage on root damage rect.
303 ClearDamageForAllSurfaces(root
.get());
304 child
->AddDamageRect(gfx::RectF(20.f
, 25.f
, 1.f
, 2.f
));
305 child
->AddDamageRect(gfx::RectF(10.f
, 15.f
, 3.f
, 4.f
));
306 EmulateDrawingOneFrame(root
.get());
308 // Damage position on the surface should be: position of layer damage_rect
309 // (20, 25) relative to the child (100, 100).
311 root
->render_surface()->damage_tracker()->current_damage_rect();
312 EXPECT_EQ(true, root_damage_rect
.Contains(gfx::Rect(120, 125, 1, 2)));
313 EXPECT_EQ(true, root_damage_rect
.Contains(gfx::Rect(110, 115, 3, 4)));
316 TEST_F(DamageTrackerTest
, VerifyDamageForLayerUpdateAndDamageRects
) {
317 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
318 LayerImpl
* child
= root
->children()[0];
320 // CASE 1: Adding the layer damage rect and update rect should cause the
321 // corresponding damage to the surface.
322 ClearDamageForAllSurfaces(root
.get());
323 child
->AddDamageRect(gfx::RectF(5.f
, 6.f
, 12.f
, 13.f
));
324 child
->SetUpdateRect(gfx::RectF(15.f
, 16.f
, 14.f
, 10.f
));
325 EmulateDrawingOneFrame(root
.get());
327 // Damage position on the surface should be: position of unified layer
328 // damage_rect and update rect (5, 6)
329 // relative to the child (100, 100).
330 gfx::Rect root_damage_rect
=
331 root
->render_surface()->damage_tracker()->current_damage_rect();
332 EXPECT_EQ(true, root_damage_rect
.Contains(gfx::Rect(105, 106, 24, 20)));
334 // CASE 2: The same layer damage rect and update rect twice in a row still
335 // produces the same damage.
336 ClearDamageForAllSurfaces(root
.get());
337 child
->AddDamageRect(gfx::RectF(10.f
, 11.f
, 12.f
, 13.f
));
338 child
->SetUpdateRect(gfx::RectF(10.f
, 11.f
, 14.f
, 15.f
));
339 EmulateDrawingOneFrame(root
.get());
341 root
->render_surface()->damage_tracker()->current_damage_rect();
342 EXPECT_EQ(true, root_damage_rect
.Contains(gfx::Rect(110, 111, 14, 15)));
344 // CASE 3: Adding a different layer damage rect and update rect should cause
345 // damage on the new damaged region, but no additional exposed old region.
346 ClearDamageForAllSurfaces(root
.get());
347 child
->AddDamageRect(gfx::RectF(20.f
, 25.f
, 2.f
, 3.f
));
348 child
->SetUpdateRect(gfx::RectF(5.f
, 10.f
, 7.f
, 8.f
));
349 EmulateDrawingOneFrame(root
.get());
351 // Damage position on the surface should be: position of unified layer damage
352 // rect and update rect (5, 10) relative to the child (100, 100).
354 root
->render_surface()->damage_tracker()->current_damage_rect();
355 EXPECT_EQ(true, root_damage_rect
.Contains(gfx::Rect(105, 110, 17, 18)));
358 TEST_F(DamageTrackerTest
, VerifyDamageForPropertyChanges
) {
359 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
360 LayerImpl
* child
= root
->children()[0];
362 // CASE 1: The layer's property changed flag takes priority over update rect.
364 ClearDamageForAllSurfaces(root
.get());
365 child
->SetUpdateRect(gfx::RectF(10.f
, 11.f
, 12.f
, 13.f
));
366 child
->SetOpacity(0.5f
);
367 EmulateDrawingOneFrame(root
.get());
369 // Sanity check - we should not have accidentally created a separate render
370 // surface for the translucent layer.
371 ASSERT_FALSE(child
->render_surface());
372 ASSERT_EQ(2u, root
->render_surface()->layer_list().size());
374 // Damage should be the entire child layer in target_surface space.
375 gfx::Rect expected_rect
= gfx::Rect(100, 100, 30, 30);
376 gfx::Rect root_damage_rect
=
377 root
->render_surface()->damage_tracker()->current_damage_rect();
378 EXPECT_EQ(expected_rect
.ToString(), root_damage_rect
.ToString());
380 // CASE 2: If a layer moves due to property change, it damages both the new
381 // location and the old (exposed) location. The old location is the
382 // entire old layer, not just the update_rect.
384 // Cycle one frame of no change, just to sanity check that the next rect is
385 // not because of the old damage state.
386 ClearDamageForAllSurfaces(root
.get());
387 EmulateDrawingOneFrame(root
.get());
389 root
->render_surface()->damage_tracker()->current_damage_rect();
390 EXPECT_TRUE(root_damage_rect
.IsEmpty());
392 // Then, test the actual layer movement.
393 ClearDamageForAllSurfaces(root
.get());
394 child
->SetPosition(gfx::PointF(200.f
, 230.f
));
395 EmulateDrawingOneFrame(root
.get());
397 // Expect damage to be the combination of the previous one and the new one.
398 expected_rect
.Union(gfx::Rect(200, 230, 30, 30));
400 root
->render_surface()->damage_tracker()->current_damage_rect();
401 EXPECT_FLOAT_RECT_EQ(expected_rect
, root_damage_rect
);
404 TEST_F(DamageTrackerTest
, VerifyDamageForTransformedLayer
) {
405 // If a layer is transformed, the damage rect should still enclose the entire
406 // transformed layer.
408 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
409 LayerImpl
* child
= root
->children()[0];
411 gfx::Transform rotation
;
412 rotation
.Rotate(45.0);
414 ClearDamageForAllSurfaces(root
.get());
415 child
->SetTransformOrigin(gfx::Point3F(
416 child
->bounds().width() * 0.5f
, child
->bounds().height() * 0.5f
, 0.f
));
417 child
->SetPosition(gfx::PointF(85.f
, 85.f
));
418 EmulateDrawingOneFrame(root
.get());
420 // Sanity check that the layer actually moved to (85, 85), damaging its old
421 // location and new location.
422 gfx::Rect root_damage_rect
=
423 root
->render_surface()->damage_tracker()->current_damage_rect();
424 EXPECT_EQ(gfx::Rect(85, 85, 45, 45).ToString(), root_damage_rect
.ToString());
426 // With the anchor on the layer's center, now we can test the rotation more
427 // intuitively, since it applies about the layer's anchor.
428 ClearDamageForAllSurfaces(root
.get());
429 child
->SetTransform(rotation
);
430 EmulateDrawingOneFrame(root
.get());
432 // Since the child layer is square, rotation by 45 degrees about the center
433 // should increase the size of the expected rect by sqrt(2), centered around
434 // (100, 100). The old exposed region should be fully contained in the new
436 float expected_width
= 30.f
* sqrt(2.f
);
437 float expected_position
= 100.f
- 0.5f
* expected_width
;
438 gfx::Rect expected_rect
= gfx::ToEnclosingRect(gfx::RectF(
439 expected_position
, expected_position
, expected_width
, expected_width
));
441 root
->render_surface()->damage_tracker()->current_damage_rect();
442 EXPECT_EQ(expected_rect
.ToString(), root_damage_rect
.ToString());
445 TEST_F(DamageTrackerTest
, VerifyDamageForPerspectiveClippedLayer
) {
446 // If a layer has a perspective transform that causes w < 0, then not
447 // clipping the layer can cause an invalid damage rect. This test checks that
448 // the w < 0 case is tracked properly.
450 // The transform is constructed so that if w < 0 clipping is not performed,
451 // the incorrect rect will be very small, specifically: position (500.972504,
452 // 498.544617) and size 0.056610 x 2.910767. Instead, the correctly
453 // transformed rect should actually be very huge (i.e. in theory, -infinity
454 // on the left), and positioned so that the right-most bound rect will be
455 // approximately 501 units in root surface space.
458 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
459 LayerImpl
* child
= root
->children()[0];
461 gfx::Transform transform
;
462 transform
.Translate3d(500.0, 500.0, 0.0);
463 transform
.ApplyPerspectiveDepth(1.0);
464 transform
.RotateAboutYAxis(45.0);
465 transform
.Translate3d(-50.0, -50.0, 0.0);
468 child
->SetPosition(gfx::PointF(0.f
, 0.f
));
469 child
->SetBounds(gfx::Size(100, 100));
470 child
->SetContentBounds(gfx::Size(100, 100));
471 child
->SetTransform(transform
);
472 EmulateDrawingOneFrame(root
.get());
474 // Sanity check that the child layer's bounds would actually get clipped by
475 // w < 0, otherwise this test is not actually testing the intended scenario.
476 gfx::QuadF
test_quad(gfx::RectF(gfx::PointF(), gfx::SizeF(100.f
, 100.f
)));
477 bool clipped
= false;
478 MathUtil::MapQuad(transform
, test_quad
, &clipped
);
479 EXPECT_TRUE(clipped
);
481 // Damage the child without moving it.
482 ClearDamageForAllSurfaces(root
.get());
483 child
->SetOpacity(0.5f
);
484 EmulateDrawingOneFrame(root
.get());
486 // The expected damage should cover the entire root surface (500x500), but we
487 // don't care whether the damage rect was clamped or is larger than the
488 // surface for this test.
489 gfx::Rect root_damage_rect
=
490 root
->render_surface()->damage_tracker()->current_damage_rect();
491 gfx::Rect damage_we_care_about
= gfx::Rect(gfx::Size(500, 500));
492 EXPECT_TRUE(root_damage_rect
.Contains(damage_we_care_about
));
495 TEST_F(DamageTrackerTest
, VerifyDamageForBlurredSurface
) {
496 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithTwoSurfaces();
497 LayerImpl
* surface
= root
->children()[0];
498 LayerImpl
* child
= surface
->children()[0];
500 FilterOperations filters
;
501 filters
.Append(FilterOperation::CreateBlurFilter(5.f
));
502 int outset_top
, outset_right
, outset_bottom
, outset_left
;
503 filters
.GetOutsets(&outset_top
, &outset_right
, &outset_bottom
, &outset_left
);
505 // Setting the filter will damage the whole surface.
506 ClearDamageForAllSurfaces(root
.get());
507 surface
->SetFilters(filters
);
508 EmulateDrawingOneFrame(root
.get());
510 // Setting the update rect should cause the corresponding damage to the
511 // surface, blurred based on the size of the blur filter.
512 ClearDamageForAllSurfaces(root
.get());
513 child
->SetUpdateRect(gfx::RectF(1.f
, 2.f
, 3.f
, 4.f
));
514 EmulateDrawingOneFrame(root
.get());
516 // Damage position on the surface should be: position of update_rect (1, 2)
517 // relative to the child (300, 300), but expanded by the blur outsets.
518 gfx::Rect root_damage_rect
=
519 root
->render_surface()->damage_tracker()->current_damage_rect();
520 gfx::Rect expected_damage_rect
= gfx::Rect(301, 302, 3, 4);
522 expected_damage_rect
.Inset(-outset_left
,
526 EXPECT_EQ(expected_damage_rect
.ToString(), root_damage_rect
.ToString());
529 TEST_F(DamageTrackerTest
, VerifyDamageForImageFilter
) {
530 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
531 LayerImpl
* child
= root
->children()[0];
532 gfx::Rect root_damage_rect
, child_damage_rect
;
534 // Allow us to set damage on child too.
535 child
->SetDrawsContent(true);
537 skia::RefPtr
<SkImageFilter
> filter
= skia::AdoptRef(
538 SkBlurImageFilter::Create(SkIntToScalar(2), SkIntToScalar(2)));
539 FilterOperations filters
;
540 filters
.Append(FilterOperation::CreateReferenceFilter(filter
));
542 // Setting the filter will damage the whole surface.
543 ClearDamageForAllSurfaces(root
.get());
544 child
->SetFilters(filters
);
545 EmulateDrawingOneFrame(root
.get());
547 root
->render_surface()->damage_tracker()->current_damage_rect();
549 child
->render_surface()->damage_tracker()->current_damage_rect();
550 EXPECT_EQ(gfx::Rect(100, 100, 30, 30).ToString(),
551 root_damage_rect
.ToString());
552 EXPECT_EQ(gfx::Rect(30, 30).ToString(), child_damage_rect
.ToString());
554 // CASE 1: Setting the update rect should damage the whole surface (for now)
555 ClearDamageForAllSurfaces(root
.get());
556 child
->SetUpdateRect(gfx::RectF(1.f
, 1.f
));
557 EmulateDrawingOneFrame(root
.get());
560 root
->render_surface()->damage_tracker()->current_damage_rect();
562 child
->render_surface()->damage_tracker()->current_damage_rect();
563 EXPECT_EQ(gfx::Rect(100, 100, 30, 30).ToString(),
564 root_damage_rect
.ToString());
565 EXPECT_EQ(gfx::Rect(30.f
, 30.f
).ToString(), child_damage_rect
.ToString());
568 TEST_F(DamageTrackerTest
, VerifyDamageForBackgroundBlurredChild
) {
569 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithTwoSurfaces();
570 LayerImpl
* child1
= root
->children()[0];
571 LayerImpl
* child2
= root
->children()[1];
573 // Allow us to set damage on child1 too.
574 child1
->SetDrawsContent(true);
576 FilterOperations filters
;
577 filters
.Append(FilterOperation::CreateBlurFilter(2.f
));
578 int outset_top
, outset_right
, outset_bottom
, outset_left
;
579 filters
.GetOutsets(&outset_top
, &outset_right
, &outset_bottom
, &outset_left
);
581 // Setting the filter will damage the whole surface.
582 ClearDamageForAllSurfaces(root
.get());
583 child1
->SetBackgroundFilters(filters
);
584 EmulateDrawingOneFrame(root
.get());
586 // CASE 1: Setting the update rect should cause the corresponding damage to
587 // the surface, blurred based on the size of the child's background
589 ClearDamageForAllSurfaces(root
.get());
590 root
->SetUpdateRect(gfx::RectF(297.f
, 297.f
, 2.f
, 2.f
));
591 EmulateDrawingOneFrame(root
.get());
593 gfx::Rect root_damage_rect
=
594 root
->render_surface()->damage_tracker()->current_damage_rect();
595 // Damage position on the surface should be a composition of the damage on
596 // the root and on child2. Damage on the root should be: position of
597 // update_rect (297, 297), but expanded by the blur outsets.
598 gfx::Rect expected_damage_rect
= gfx::Rect(297, 297, 2, 2);
600 expected_damage_rect
.Inset(-outset_left
,
604 EXPECT_EQ(expected_damage_rect
.ToString(), root_damage_rect
.ToString());
606 // CASE 2: Setting the update rect should cause the corresponding damage to
607 // the surface, blurred based on the size of the child's background
608 // blur filter. Since the damage extends to the right/bottom outside
609 // of the blurred layer, only the left/top should end up expanded.
610 ClearDamageForAllSurfaces(root
.get());
611 root
->SetUpdateRect(gfx::RectF(297.f
, 297.f
, 30.f
, 30.f
));
612 EmulateDrawingOneFrame(root
.get());
615 root
->render_surface()->damage_tracker()->current_damage_rect();
616 // Damage position on the surface should be a composition of the damage on
617 // the root and on child2. Damage on the root should be: position of
618 // update_rect (297, 297), but expanded on the left/top by the blur outsets.
619 expected_damage_rect
= gfx::Rect(297, 297, 30, 30);
621 expected_damage_rect
.Inset(-outset_left
,
625 EXPECT_EQ(expected_damage_rect
.ToString(), root_damage_rect
.ToString());
627 // CASE 3: Setting this update rect outside the blurred content_bounds of the
628 // blurred child1 will not cause it to be expanded.
629 ClearDamageForAllSurfaces(root
.get());
630 root
->SetUpdateRect(gfx::RectF(30.f
, 30.f
, 2.f
, 2.f
));
631 EmulateDrawingOneFrame(root
.get());
634 root
->render_surface()->damage_tracker()->current_damage_rect();
635 // Damage on the root should be: position of update_rect (30, 30), not
637 expected_damage_rect
= gfx::Rect(30, 30, 2, 2);
639 EXPECT_EQ(expected_damage_rect
.ToString(), root_damage_rect
.ToString());
641 // CASE 4: Setting this update rect inside the blurred content_bounds but
642 // outside the original content_bounds of the blurred child1 will
643 // cause it to be expanded.
644 ClearDamageForAllSurfaces(root
.get());
645 root
->SetUpdateRect(gfx::RectF(99.f
, 99.f
, 1.f
, 1.f
));
646 EmulateDrawingOneFrame(root
.get());
649 root
->render_surface()->damage_tracker()->current_damage_rect();
650 // Damage on the root should be: position of update_rect (99, 99), expanded by
651 // the blurring on child1, but since it is 1 pixel outside the layer, the
652 // expanding should be reduced by 1.
653 expected_damage_rect
= gfx::Rect(99, 99, 1, 1);
655 expected_damage_rect
.Inset(-outset_left
+ 1,
659 EXPECT_EQ(expected_damage_rect
.ToString(), root_damage_rect
.ToString());
661 // CASE 5: Setting the update rect on child2, which is above child1, will
662 // not get blurred by child1, so it does not need to get expanded.
663 ClearDamageForAllSurfaces(root
.get());
664 child2
->SetUpdateRect(gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
));
665 EmulateDrawingOneFrame(root
.get());
668 root
->render_surface()->damage_tracker()->current_damage_rect();
669 // Damage on child2 should be: position of update_rect offset by the child's
670 // position (11, 11), and not expanded by anything.
671 expected_damage_rect
= gfx::Rect(11, 11, 1, 1);
673 EXPECT_EQ(expected_damage_rect
.ToString(), root_damage_rect
.ToString());
675 // CASE 6: Setting the update rect on child1 will also blur the damage, so
676 // that any pixels needed for the blur are redrawn in the current
678 ClearDamageForAllSurfaces(root
.get());
679 child1
->SetUpdateRect(gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
));
680 EmulateDrawingOneFrame(root
.get());
683 root
->render_surface()->damage_tracker()->current_damage_rect();
684 // Damage on child1 should be: position of update_rect offset by the child's
685 // position (100, 100), and expanded by the damage.
686 expected_damage_rect
= gfx::Rect(100, 100, 1, 1);
688 expected_damage_rect
.Inset(-outset_left
,
692 EXPECT_EQ(expected_damage_rect
.ToString(), root_damage_rect
.ToString());
695 TEST_F(DamageTrackerTest
, VerifyDamageForAddingAndRemovingLayer
) {
696 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
697 LayerImpl
* child1
= root
->children()[0];
699 // CASE 1: Adding a new layer should cause the appropriate damage.
701 ClearDamageForAllSurfaces(root
.get());
703 scoped_ptr
<LayerImpl
> child2
=
704 LayerImpl::Create(host_impl_
.active_tree(), 3);
705 child2
->SetPosition(gfx::PointF(400.f
, 380.f
));
706 child2
->SetBounds(gfx::Size(6, 8));
707 child2
->SetContentBounds(gfx::Size(6, 8));
708 child2
->SetDrawsContent(true);
709 root
->AddChild(child2
.Pass());
711 EmulateDrawingOneFrame(root
.get());
713 // Sanity check - all 3 layers should be on the same render surface; render
714 // surfaces are tested elsewhere.
715 ASSERT_EQ(3u, root
->render_surface()->layer_list().size());
717 gfx::Rect root_damage_rect
=
718 root
->render_surface()->damage_tracker()->current_damage_rect();
719 EXPECT_EQ(gfx::Rect(400, 380, 6, 8).ToString(), root_damage_rect
.ToString());
721 // CASE 2: If the layer is removed, its entire old layer becomes exposed, not
722 // just the last update rect.
724 // Advance one frame without damage so that we know the damage rect is not
725 // leftover from the previous case.
726 ClearDamageForAllSurfaces(root
.get());
727 EmulateDrawingOneFrame(root
.get());
730 root
->render_surface()->damage_tracker()->current_damage_rect();
731 EXPECT_TRUE(root_damage_rect
.IsEmpty());
733 // Then, test removing child1.
734 root
->RemoveChild(child1
);
736 EmulateDrawingOneFrame(root
.get());
739 root
->render_surface()->damage_tracker()->current_damage_rect();
740 EXPECT_EQ(gfx::Rect(100, 100, 30, 30).ToString(),
741 root_damage_rect
.ToString());
744 TEST_F(DamageTrackerTest
, VerifyDamageForNewUnchangedLayer
) {
745 // If child2 is added to the layer tree, but it doesn't have any explicit
746 // damage of its own, it should still indeed damage the target surface.
748 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
750 ClearDamageForAllSurfaces(root
.get());
752 scoped_ptr
<LayerImpl
> child2
=
753 LayerImpl::Create(host_impl_
.active_tree(), 3);
754 child2
->SetPosition(gfx::PointF(400.f
, 380.f
));
755 child2
->SetBounds(gfx::Size(6, 8));
756 child2
->SetContentBounds(gfx::Size(6, 8));
757 child2
->SetDrawsContent(true);
758 child2
->ResetAllChangeTrackingForSubtree();
759 // Sanity check the initial conditions of the test, if these asserts
760 // trigger, it means the test no longer actually covers the intended
762 ASSERT_FALSE(child2
->LayerPropertyChanged());
763 ASSERT_TRUE(child2
->update_rect().IsEmpty());
764 root
->AddChild(child2
.Pass());
766 EmulateDrawingOneFrame(root
.get());
768 // Sanity check - all 3 layers should be on the same render surface; render
769 // surfaces are tested elsewhere.
770 ASSERT_EQ(3u, root
->render_surface()->layer_list().size());
772 gfx::Rect root_damage_rect
=
773 root
->render_surface()->damage_tracker()->current_damage_rect();
774 EXPECT_EQ(gfx::Rect(400, 380, 6, 8).ToString(), root_damage_rect
.ToString());
777 TEST_F(DamageTrackerTest
, VerifyDamageForMultipleLayers
) {
778 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
779 LayerImpl
* child1
= root
->children()[0];
781 // In this test we don't want the above tree manipulation to be considered
782 // part of the same frame.
783 ClearDamageForAllSurfaces(root
.get());
785 scoped_ptr
<LayerImpl
> child2
=
786 LayerImpl::Create(host_impl_
.active_tree(), 3);
787 child2
->SetPosition(gfx::PointF(400.f
, 380.f
));
788 child2
->SetBounds(gfx::Size(6, 8));
789 child2
->SetContentBounds(gfx::Size(6, 8));
790 child2
->SetDrawsContent(true);
791 root
->AddChild(child2
.Pass());
793 LayerImpl
* child2
= root
->children()[1];
794 EmulateDrawingOneFrame(root
.get());
796 // Damaging two layers simultaneously should cause combined damage.
797 // - child1 update rect in surface space: gfx::Rect(100, 100, 1, 2);
798 // - child2 update rect in surface space: gfx::Rect(400, 380, 3, 4);
799 ClearDamageForAllSurfaces(root
.get());
800 child1
->SetUpdateRect(gfx::RectF(0.f
, 0.f
, 1.f
, 2.f
));
801 child2
->SetUpdateRect(gfx::RectF(0.f
, 0.f
, 3.f
, 4.f
));
802 EmulateDrawingOneFrame(root
.get());
803 gfx::Rect root_damage_rect
=
804 root
->render_surface()->damage_tracker()->current_damage_rect();
805 EXPECT_EQ(gfx::Rect(100, 100, 303, 284).ToString(),
806 root_damage_rect
.ToString());
809 TEST_F(DamageTrackerTest
, VerifyDamageForNestedSurfaces
) {
810 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithTwoSurfaces();
811 LayerImpl
* child1
= root
->children()[0];
812 LayerImpl
* child2
= root
->children()[1];
813 LayerImpl
* grand_child1
= root
->children()[0]->children()[0];
814 gfx::Rect child_damage_rect
;
815 gfx::Rect root_damage_rect
;
817 // CASE 1: Damage to a descendant surface should propagate properly to
819 ClearDamageForAllSurfaces(root
.get());
820 grand_child1
->SetOpacity(0.5f
);
821 EmulateDrawingOneFrame(root
.get());
823 child1
->render_surface()->damage_tracker()->current_damage_rect();
825 root
->render_surface()->damage_tracker()->current_damage_rect();
826 EXPECT_EQ(gfx::Rect(200, 200, 6, 8).ToString(), child_damage_rect
.ToString());
827 EXPECT_EQ(gfx::Rect(300, 300, 6, 8).ToString(), root_damage_rect
.ToString());
829 // CASE 2: Same as previous case, but with additional damage elsewhere that
830 // should be properly unioned.
831 // - child1 surface damage in root surface space:
832 // gfx::Rect(300, 300, 6, 8);
833 // - child2 damage in root surface space:
834 // gfx::Rect(11, 11, 18, 18);
835 ClearDamageForAllSurfaces(root
.get());
836 grand_child1
->SetOpacity(0.7f
);
837 child2
->SetOpacity(0.7f
);
838 EmulateDrawingOneFrame(root
.get());
840 child1
->render_surface()->damage_tracker()->current_damage_rect();
842 root
->render_surface()->damage_tracker()->current_damage_rect();
843 EXPECT_EQ(gfx::Rect(200, 200, 6, 8).ToString(), child_damage_rect
.ToString());
844 EXPECT_EQ(gfx::Rect(11, 11, 295, 297).ToString(),
845 root_damage_rect
.ToString());
848 TEST_F(DamageTrackerTest
, VerifyDamageForSurfaceChangeFromDescendantLayer
) {
849 // If descendant layer changes and affects the content bounds of the render
850 // surface, then the entire descendant surface should be damaged, and it
851 // should damage its ancestor surface with the old and new surface regions.
853 // This is a tricky case, since only the first grand_child changes, but the
854 // entire surface should be marked dirty.
856 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithTwoSurfaces();
857 LayerImpl
* child1
= root
->children()[0];
858 LayerImpl
* grand_child1
= root
->children()[0]->children()[0];
859 gfx::Rect child_damage_rect
;
860 gfx::Rect root_damage_rect
;
862 ClearDamageForAllSurfaces(root
.get());
863 grand_child1
->SetPosition(gfx::PointF(195.f
, 205.f
));
864 EmulateDrawingOneFrame(root
.get());
866 child1
->render_surface()->damage_tracker()->current_damage_rect();
868 root
->render_surface()->damage_tracker()->current_damage_rect();
870 // The new surface bounds should be damaged entirely, even though only one of
871 // the layers changed.
872 EXPECT_EQ(gfx::Rect(190, 190, 11, 23).ToString(),
873 child_damage_rect
.ToString());
875 // Damage to the root surface should be the union of child1's *entire* render
876 // surface (in target space), and its old exposed area (also in target
878 EXPECT_EQ(gfx::Rect(290, 290, 16, 23).ToString(),
879 root_damage_rect
.ToString());
882 TEST_F(DamageTrackerTest
, VerifyDamageForSurfaceChangeFromAncestorLayer
) {
883 // An ancestor/owning layer changes that affects the position/transform of
884 // the render surface. Note that in this case, the layer_property_changed flag
885 // already propagates to the subtree (tested in LayerImpltest), which damages
886 // the entire child1 surface, but the damage tracker still needs the correct
887 // logic to compute the exposed region on the root surface.
889 // TODO(shawnsingh): the expectations of this test case should change when we
890 // add support for a unique scissor_rect per RenderSurface. In that case, the
891 // child1 surface should be completely unchanged, since we are only
892 // transforming it, while the root surface would be damaged appropriately.
894 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithTwoSurfaces();
895 LayerImpl
* child1
= root
->children()[0];
896 gfx::Rect child_damage_rect
;
897 gfx::Rect root_damage_rect
;
899 ClearDamageForAllSurfaces(root
.get());
900 child1
->SetPosition(gfx::PointF(50.f
, 50.f
));
901 EmulateDrawingOneFrame(root
.get());
903 child1
->render_surface()->damage_tracker()->current_damage_rect();
905 root
->render_surface()->damage_tracker()->current_damage_rect();
907 // The new surface bounds should be damaged entirely.
908 EXPECT_EQ(gfx::Rect(190, 190, 16, 18).ToString(),
909 child_damage_rect
.ToString());
911 // The entire child1 surface and the old exposed child1 surface should damage
913 // - old child1 surface in target space: gfx::Rect(290, 290, 16, 18)
914 // - new child1 surface in target space: gfx::Rect(240, 240, 16, 18)
915 EXPECT_EQ(gfx::Rect(240, 240, 66, 68).ToString(),
916 root_damage_rect
.ToString());
919 TEST_F(DamageTrackerTest
, VerifyDamageForAddingAndRemovingRenderSurfaces
) {
920 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithTwoSurfaces();
921 LayerImpl
* child1
= root
->children()[0];
922 gfx::Rect child_damage_rect
;
923 gfx::Rect root_damage_rect
;
925 // CASE 1: If a descendant surface disappears, its entire old area becomes
927 ClearDamageForAllSurfaces(root
.get());
928 child1
->SetOpacity(1.f
);
929 child1
->SetForceRenderSurface(false);
930 EmulateDrawingOneFrame(root
.get());
932 // Sanity check that there is only one surface now.
933 ASSERT_FALSE(child1
->render_surface());
934 ASSERT_EQ(4u, root
->render_surface()->layer_list().size());
937 root
->render_surface()->damage_tracker()->current_damage_rect();
938 EXPECT_EQ(gfx::Rect(290, 290, 16, 18).ToString(),
939 root_damage_rect
.ToString());
941 // CASE 2: If a descendant surface appears, its entire old area becomes
944 // Cycle one frame of no change, just to sanity check that the next rect is
945 // not because of the old damage state.
946 ClearDamageForAllSurfaces(root
.get());
947 EmulateDrawingOneFrame(root
.get());
949 root
->render_surface()->damage_tracker()->current_damage_rect();
950 EXPECT_TRUE(root_damage_rect
.IsEmpty());
952 // Then change the tree so that the render surface is added back.
953 ClearDamageForAllSurfaces(root
.get());
954 child1
->SetOpacity(0.5f
);
955 child1
->SetForceRenderSurface(true);
956 EmulateDrawingOneFrame(root
.get());
958 // Sanity check that there is a new surface now.
959 ASSERT_TRUE(child1
->render_surface());
960 EXPECT_EQ(3u, root
->render_surface()->layer_list().size());
961 EXPECT_EQ(2u, child1
->render_surface()->layer_list().size());
964 child1
->render_surface()->damage_tracker()->current_damage_rect();
966 root
->render_surface()->damage_tracker()->current_damage_rect();
967 EXPECT_EQ(gfx::Rect(190, 190, 16, 18).ToString(),
968 child_damage_rect
.ToString());
969 EXPECT_EQ(gfx::Rect(290, 290, 16, 18).ToString(),
970 root_damage_rect
.ToString());
973 TEST_F(DamageTrackerTest
, VerifyNoDamageWhenNothingChanged
) {
974 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithTwoSurfaces();
975 LayerImpl
* child1
= root
->children()[0];
976 gfx::Rect child_damage_rect
;
977 gfx::Rect root_damage_rect
;
979 // CASE 1: If nothing changes, the damage rect should be empty.
981 ClearDamageForAllSurfaces(root
.get());
982 EmulateDrawingOneFrame(root
.get());
984 child1
->render_surface()->damage_tracker()->current_damage_rect();
986 root
->render_surface()->damage_tracker()->current_damage_rect();
987 EXPECT_TRUE(child_damage_rect
.IsEmpty());
988 EXPECT_TRUE(root_damage_rect
.IsEmpty());
990 // CASE 2: If nothing changes twice in a row, the damage rect should still be
993 ClearDamageForAllSurfaces(root
.get());
994 EmulateDrawingOneFrame(root
.get());
996 child1
->render_surface()->damage_tracker()->current_damage_rect();
998 root
->render_surface()->damage_tracker()->current_damage_rect();
999 EXPECT_TRUE(child_damage_rect
.IsEmpty());
1000 EXPECT_TRUE(root_damage_rect
.IsEmpty());
1003 TEST_F(DamageTrackerTest
, VerifyNoDamageForUpdateRectThatDoesNotDrawContent
) {
1004 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithTwoSurfaces();
1005 LayerImpl
* child1
= root
->children()[0];
1006 gfx::Rect child_damage_rect
;
1007 gfx::Rect root_damage_rect
;
1009 // In our specific tree, the update rect of child1 should not cause any
1010 // damage to any surface because it does not actually draw content.
1011 ClearDamageForAllSurfaces(root
.get());
1012 child1
->SetUpdateRect(gfx::RectF(0.f
, 0.f
, 1.f
, 2.f
));
1013 EmulateDrawingOneFrame(root
.get());
1015 child1
->render_surface()->damage_tracker()->current_damage_rect();
1017 root
->render_surface()->damage_tracker()->current_damage_rect();
1018 EXPECT_TRUE(child_damage_rect
.IsEmpty());
1019 EXPECT_TRUE(root_damage_rect
.IsEmpty());
1022 TEST_F(DamageTrackerTest
, VerifyDamageForReplica
) {
1023 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithTwoSurfaces();
1024 LayerImpl
* child1
= root
->children()[0];
1025 LayerImpl
* grand_child1
= child1
->children()[0];
1026 LayerImpl
* grand_child2
= child1
->children()[1];
1028 // Damage on a surface that has a reflection should cause the target surface
1029 // to receive the surface's damage and the surface's reflected damage.
1031 // For this test case, we modify grand_child2, and add grand_child3 to extend
1032 // the bounds of child1's surface. This way, we can test reflection changes
1033 // without changing content_bounds of the surface.
1034 grand_child2
->SetPosition(gfx::PointF(180.f
, 180.f
));
1036 scoped_ptr
<LayerImpl
> grand_child3
=
1037 LayerImpl::Create(host_impl_
.active_tree(), 6);
1038 grand_child3
->SetPosition(gfx::PointF(240.f
, 240.f
));
1039 grand_child3
->SetBounds(gfx::Size(10, 10));
1040 grand_child3
->SetContentBounds(gfx::Size(10, 10));
1041 grand_child3
->SetDrawsContent(true);
1042 child1
->AddChild(grand_child3
.Pass());
1044 child1
->SetOpacity(0.5f
);
1045 EmulateDrawingOneFrame(root
.get());
1047 // CASE 1: adding a reflection about the left edge of grand_child1.
1049 ClearDamageForAllSurfaces(root
.get());
1051 scoped_ptr
<LayerImpl
> grand_child1_replica
=
1052 LayerImpl::Create(host_impl_
.active_tree(), 7);
1053 grand_child1_replica
->SetPosition(gfx::PointF());
1054 gfx::Transform reflection
;
1055 reflection
.Scale3d(-1.0, 1.0, 1.0);
1056 grand_child1_replica
->SetTransform(reflection
);
1057 grand_child1
->SetReplicaLayer(grand_child1_replica
.Pass());
1059 EmulateDrawingOneFrame(root
.get());
1061 gfx::Rect grand_child_damage_rect
=
1062 grand_child1
->render_surface()->damage_tracker()->current_damage_rect();
1063 gfx::Rect child_damage_rect
=
1064 child1
->render_surface()->damage_tracker()->current_damage_rect();
1065 gfx::Rect root_damage_rect
=
1066 root
->render_surface()->damage_tracker()->current_damage_rect();
1068 // The grand_child surface damage should not include its own replica. The
1069 // child surface damage should include the normal and replica surfaces.
1070 EXPECT_EQ(gfx::Rect(6, 8).ToString(), grand_child_damage_rect
.ToString());
1071 EXPECT_EQ(gfx::Rect(194, 200, 12, 8).ToString(),
1072 child_damage_rect
.ToString());
1073 EXPECT_EQ(gfx::Rect(294, 300, 12, 8).ToString(), root_damage_rect
.ToString());
1075 // CASE 2: moving the descendant surface should cause both the original and
1076 // reflected areas to be damaged on the target.
1077 ClearDamageForAllSurfaces(root
.get());
1078 gfx::Rect old_content_rect
= child1
->render_surface()->content_rect();
1079 grand_child1
->SetPosition(gfx::PointF(195.f
, 205.f
));
1080 EmulateDrawingOneFrame(root
.get());
1081 ASSERT_EQ(old_content_rect
.width(),
1082 child1
->render_surface()->content_rect().width());
1083 ASSERT_EQ(old_content_rect
.height(),
1084 child1
->render_surface()->content_rect().height());
1086 grand_child_damage_rect
=
1087 grand_child1
->render_surface()->
1088 damage_tracker()->current_damage_rect();
1090 child1
->render_surface()->damage_tracker()->current_damage_rect();
1092 root
->render_surface()->damage_tracker()->current_damage_rect();
1094 // The child surface damage should include normal and replica surfaces for
1095 // both old and new locations.
1096 // - old location in target space: gfx::Rect(194, 200, 12, 8)
1097 // - new location in target space: gfx::Rect(189, 205, 12, 8)
1098 EXPECT_EQ(gfx::Rect(6, 8).ToString(), grand_child_damage_rect
.ToString());
1099 EXPECT_EQ(gfx::Rect(189, 200, 17, 13).ToString(),
1100 child_damage_rect
.ToString());
1101 EXPECT_EQ(gfx::Rect(289, 300, 17, 13).ToString(),
1102 root_damage_rect
.ToString());
1104 // CASE 3: removing the reflection should cause the entire region including
1105 // reflection to damage the target surface.
1106 ClearDamageForAllSurfaces(root
.get());
1107 grand_child1
->SetReplicaLayer(scoped_ptr
<LayerImpl
>());
1108 EmulateDrawingOneFrame(root
.get());
1109 ASSERT_EQ(old_content_rect
.width(),
1110 child1
->render_surface()->content_rect().width());
1111 ASSERT_EQ(old_content_rect
.height(),
1112 child1
->render_surface()->content_rect().height());
1114 EXPECT_FALSE(grand_child1
->render_surface());
1116 child1
->render_surface()->damage_tracker()->current_damage_rect();
1118 root
->render_surface()->damage_tracker()->current_damage_rect();
1120 EXPECT_EQ(gfx::Rect(189, 205, 12, 8).ToString(),
1121 child_damage_rect
.ToString());
1122 EXPECT_EQ(gfx::Rect(289, 305, 12, 8).ToString(), root_damage_rect
.ToString());
1125 TEST_F(DamageTrackerTest
, VerifyDamageForMask
) {
1126 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
1127 LayerImpl
* child
= root
->children()[0];
1129 // In the current implementation of the damage tracker, changes to mask
1130 // layers should damage the entire corresponding surface.
1132 ClearDamageForAllSurfaces(root
.get());
1134 // Set up the mask layer.
1136 scoped_ptr
<LayerImpl
> mask_layer
=
1137 LayerImpl::Create(host_impl_
.active_tree(), 3);
1138 mask_layer
->SetPosition(child
->position());
1139 mask_layer
->SetBounds(child
->bounds());
1140 mask_layer
->SetContentBounds(child
->bounds());
1141 child
->SetMaskLayer(mask_layer
.Pass());
1143 LayerImpl
* mask_layer
= child
->mask_layer();
1145 // Add opacity and a grand_child so that the render surface persists even
1146 // after we remove the mask.
1147 child
->SetOpacity(0.5f
);
1149 scoped_ptr
<LayerImpl
> grand_child
=
1150 LayerImpl::Create(host_impl_
.active_tree(), 4);
1151 grand_child
->SetPosition(gfx::PointF(2.f
, 2.f
));
1152 grand_child
->SetBounds(gfx::Size(2, 2));
1153 grand_child
->SetContentBounds(gfx::Size(2, 2));
1154 grand_child
->SetDrawsContent(true);
1155 child
->AddChild(grand_child
.Pass());
1157 EmulateDrawingOneFrame(root
.get());
1159 // Sanity check that a new surface was created for the child.
1160 ASSERT_TRUE(child
->render_surface());
1162 // CASE 1: the update_rect on a mask layer should damage the entire target
1164 ClearDamageForAllSurfaces(root
.get());
1165 mask_layer
->SetUpdateRect(gfx::RectF(1.f
, 2.f
, 3.f
, 4.f
));
1166 EmulateDrawingOneFrame(root
.get());
1167 gfx::Rect child_damage_rect
=
1168 child
->render_surface()->damage_tracker()->current_damage_rect();
1169 EXPECT_EQ(gfx::Rect(30, 30).ToString(), child_damage_rect
.ToString());
1171 // CASE 2: a property change on the mask layer should damage the entire
1174 // Advance one frame without damage so that we know the damage rect is not
1175 // leftover from the previous case.
1176 ClearDamageForAllSurfaces(root
.get());
1177 EmulateDrawingOneFrame(root
.get());
1179 child
->render_surface()->damage_tracker()->current_damage_rect();
1180 EXPECT_TRUE(child_damage_rect
.IsEmpty());
1182 // Then test the property change.
1183 ClearDamageForAllSurfaces(root
.get());
1184 mask_layer
->SetStackingOrderChanged(true);
1186 EmulateDrawingOneFrame(root
.get());
1188 child
->render_surface()->damage_tracker()->current_damage_rect();
1189 EXPECT_EQ(gfx::Rect(30, 30).ToString(), child_damage_rect
.ToString());
1191 // CASE 3: removing the mask also damages the entire target surface.
1194 // Advance one frame without damage so that we know the damage rect is not
1195 // leftover from the previous case.
1196 ClearDamageForAllSurfaces(root
.get());
1197 EmulateDrawingOneFrame(root
.get());
1199 child
->render_surface()->damage_tracker()->current_damage_rect();
1200 EXPECT_TRUE(child_damage_rect
.IsEmpty());
1202 // Then test mask removal.
1203 ClearDamageForAllSurfaces(root
.get());
1204 child
->SetMaskLayer(scoped_ptr
<LayerImpl
>());
1205 ASSERT_TRUE(child
->LayerPropertyChanged());
1206 EmulateDrawingOneFrame(root
.get());
1208 // Sanity check that a render surface still exists.
1209 ASSERT_TRUE(child
->render_surface());
1212 child
->render_surface()->damage_tracker()->current_damage_rect();
1213 EXPECT_EQ(gfx::Rect(30, 30).ToString(), child_damage_rect
.ToString());
1216 TEST_F(DamageTrackerTest
, VerifyDamageForReplicaMask
) {
1217 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithTwoSurfaces();
1218 LayerImpl
* child1
= root
->children()[0];
1219 LayerImpl
* grand_child1
= child1
->children()[0];
1221 // Changes to a replica's mask should not damage the original surface,
1222 // because it is not masked. But it does damage the ancestor target surface.
1224 ClearDamageForAllSurfaces(root
.get());
1226 // Create a reflection about the left edge of grand_child1.
1228 scoped_ptr
<LayerImpl
> grand_child1_replica
=
1229 LayerImpl::Create(host_impl_
.active_tree(), 6);
1230 grand_child1_replica
->SetPosition(gfx::PointF());
1231 gfx::Transform reflection
;
1232 reflection
.Scale3d(-1.0, 1.0, 1.0);
1233 grand_child1_replica
->SetTransform(reflection
);
1234 grand_child1
->SetReplicaLayer(grand_child1_replica
.Pass());
1236 LayerImpl
* grand_child1_replica
= grand_child1
->replica_layer();
1238 // Set up the mask layer on the replica layer
1240 scoped_ptr
<LayerImpl
> replica_mask_layer
=
1241 LayerImpl::Create(host_impl_
.active_tree(), 7);
1242 replica_mask_layer
->SetPosition(gfx::PointF());
1243 replica_mask_layer
->SetBounds(grand_child1
->bounds());
1244 replica_mask_layer
->SetContentBounds(grand_child1
->bounds());
1245 grand_child1_replica
->SetMaskLayer(replica_mask_layer
.Pass());
1247 LayerImpl
* replica_mask_layer
= grand_child1_replica
->mask_layer();
1249 EmulateDrawingOneFrame(root
.get());
1251 // Sanity check that the appropriate render surfaces were created
1252 ASSERT_TRUE(grand_child1
->render_surface());
1254 // CASE 1: a property change on the mask should damage only the reflected
1255 // region on the target surface.
1256 ClearDamageForAllSurfaces(root
.get());
1257 replica_mask_layer
->SetStackingOrderChanged(true);
1258 EmulateDrawingOneFrame(root
.get());
1260 gfx::Rect grand_child_damage_rect
=
1261 grand_child1
->render_surface()->damage_tracker()->current_damage_rect();
1262 gfx::Rect child_damage_rect
=
1263 child1
->render_surface()->damage_tracker()->current_damage_rect();
1265 EXPECT_TRUE(grand_child_damage_rect
.IsEmpty());
1266 EXPECT_EQ(gfx::Rect(194, 200, 6, 8).ToString(), child_damage_rect
.ToString());
1268 // CASE 2: removing the replica mask damages only the reflected region on the
1271 ClearDamageForAllSurfaces(root
.get());
1272 grand_child1_replica
->SetMaskLayer(scoped_ptr
<LayerImpl
>());
1273 EmulateDrawingOneFrame(root
.get());
1275 grand_child_damage_rect
=
1276 grand_child1
->render_surface()->damage_tracker()->
1277 current_damage_rect();
1279 child1
->render_surface()->damage_tracker()->current_damage_rect();
1281 EXPECT_TRUE(grand_child_damage_rect
.IsEmpty());
1282 EXPECT_EQ(gfx::Rect(194, 200, 6, 8).ToString(), child_damage_rect
.ToString());
1285 TEST_F(DamageTrackerTest
, VerifyDamageForReplicaMaskWithTransformOrigin
) {
1286 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithTwoSurfaces();
1287 LayerImpl
* child1
= root
->children()[0];
1288 LayerImpl
* grand_child1
= child1
->children()[0];
1290 // Verify that the correct replica_origin_transform is used for the
1292 ClearDamageForAllSurfaces(root
.get());
1294 // This is not actually the transform origin point being tested, but by
1296 // expected to be the same as the replica's anchor point.
1297 grand_child1
->SetTransformOrigin(
1298 gfx::Point3F(grand_child1
->bounds().width(), 0.f
, 0.f
));
1301 scoped_ptr
<LayerImpl
> grand_child1_replica
=
1302 LayerImpl::Create(host_impl_
.active_tree(), 6);
1303 grand_child1_replica
->SetPosition(gfx::PointF());
1305 // This is the anchor being tested.
1306 grand_child1_replica
->SetTransformOrigin(
1307 gfx::Point3F(grand_child1
->bounds().width(), 0.f
, 0.f
));
1308 gfx::Transform reflection
;
1309 reflection
.Scale3d(-1.0, 1.0, 1.0);
1310 grand_child1_replica
->SetTransform(reflection
);
1311 grand_child1
->SetReplicaLayer(grand_child1_replica
.Pass());
1313 LayerImpl
* grand_child1_replica
= grand_child1
->replica_layer();
1315 // Set up the mask layer on the replica layer
1317 scoped_ptr
<LayerImpl
> replica_mask_layer
=
1318 LayerImpl::Create(host_impl_
.active_tree(), 7);
1319 replica_mask_layer
->SetPosition(gfx::PointF());
1320 // Note: this is not the transform origin being tested.
1321 replica_mask_layer
->SetBounds(grand_child1
->bounds());
1322 replica_mask_layer
->SetContentBounds(grand_child1
->bounds());
1323 grand_child1_replica
->SetMaskLayer(replica_mask_layer
.Pass());
1325 LayerImpl
* replica_mask_layer
= grand_child1_replica
->mask_layer();
1327 EmulateDrawingOneFrame(root
.get());
1329 // Sanity check that the appropriate render surfaces were created
1330 ASSERT_TRUE(grand_child1
->render_surface());
1332 // A property change on the replica_mask should damage the reflected region on
1333 // the target surface.
1334 ClearDamageForAllSurfaces(root
.get());
1335 replica_mask_layer
->SetStackingOrderChanged(true);
1337 EmulateDrawingOneFrame(root
.get());
1339 gfx::Rect child_damage_rect
=
1340 child1
->render_surface()->damage_tracker()->current_damage_rect();
1341 EXPECT_EQ(gfx::Rect(206, 200, 6, 8).ToString(), child_damage_rect
.ToString());
1344 TEST_F(DamageTrackerTest
, DamageWhenAddedExternally
) {
1345 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
1346 LayerImpl
* child
= root
->children()[0];
1348 // Case 1: This test ensures that when the tracker is given damage, that
1349 // it is included with any other partial damage.
1351 ClearDamageForAllSurfaces(root
.get());
1352 child
->SetUpdateRect(gfx::RectF(10, 11, 12, 13));
1353 root
->render_surface()->damage_tracker()->AddDamageNextUpdate(
1354 gfx::Rect(15, 16, 32, 33));
1355 EmulateDrawingOneFrame(root
.get());
1356 gfx::Rect root_damage_rect
=
1357 root
->render_surface()->damage_tracker()->current_damage_rect();
1358 EXPECT_EQ(gfx::UnionRects(gfx::Rect(15, 16, 32, 33),
1359 gfx::Rect(100 + 10, 100 + 11, 12, 13)).ToString(),
1360 root_damage_rect
.ToString());
1362 // Case 2: An additional sanity check that adding damage works even when
1363 // nothing on the layer tree changed.
1365 ClearDamageForAllSurfaces(root
.get());
1366 root
->render_surface()->damage_tracker()->AddDamageNextUpdate(
1367 gfx::Rect(30, 31, 14, 15));
1368 EmulateDrawingOneFrame(root
.get());
1370 root
->render_surface()->damage_tracker()->current_damage_rect();
1371 EXPECT_EQ(gfx::Rect(30, 31, 14, 15).ToString(), root_damage_rect
.ToString());
1374 TEST_F(DamageTrackerTest
, VerifyDamageForEmptyLayerList
) {
1375 // Though it should never happen, its a good idea to verify that the damage
1376 // tracker does not crash when it receives an empty layer_list.
1378 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
.active_tree(), 1);
1379 root
->CreateRenderSurface();
1381 ASSERT_TRUE(root
== root
->render_target());
1382 RenderSurfaceImpl
* target_surface
= root
->render_surface();
1384 LayerImplList empty_list
;
1385 target_surface
->damage_tracker()->UpdateDamageTrackingState(
1387 target_surface
->OwningLayerId(),
1391 FilterOperations());
1393 gfx::Rect damage_rect
=
1394 target_surface
->damage_tracker()->current_damage_rect();
1395 EXPECT_TRUE(damage_rect
.IsEmpty());
1398 TEST_F(DamageTrackerTest
, VerifyDamageAccumulatesUntilReset
) {
1399 // If damage is not cleared, it should accumulate.
1401 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
1402 LayerImpl
* child
= root
->children()[0];
1404 ClearDamageForAllSurfaces(root
.get());
1405 child
->SetUpdateRect(gfx::Rect(10.f
, 11.f
, 1.f
, 2.f
));
1406 EmulateDrawingOneFrame(root
.get());
1408 // Sanity check damage after the first frame; this isnt the actual test yet.
1409 gfx::Rect root_damage_rect
=
1410 root
->render_surface()->damage_tracker()->current_damage_rect();
1411 EXPECT_EQ(gfx::Rect(110, 111, 1, 2).ToString(), root_damage_rect
.ToString());
1413 // New damage, without having cleared the previous damage, should be unioned
1414 // to the previous one.
1415 child
->SetUpdateRect(gfx::RectF(20.f
, 25.f
, 1.f
, 2.f
));
1416 EmulateDrawingOneFrame(root
.get());
1418 root
->render_surface()->damage_tracker()->current_damage_rect();
1419 EXPECT_EQ(gfx::Rect(110, 111, 11, 16).ToString(),
1420 root_damage_rect
.ToString());
1422 // If we notify the damage tracker that we drew the damaged area, then damage
1423 // should be emptied.
1424 root
->render_surface()->damage_tracker()->DidDrawDamagedArea();
1426 root
->render_surface()->damage_tracker()->current_damage_rect();
1427 EXPECT_TRUE(root_damage_rect
.IsEmpty());
1429 // Damage should remain empty even after one frame, since there's yet no new
1431 EmulateDrawingOneFrame(root
.get());
1433 root
->render_surface()->damage_tracker()->current_damage_rect();
1434 EXPECT_TRUE(root_damage_rect
.IsEmpty());
1437 TEST_F(DamageTrackerTest
, HugeDamageRect
) {
1438 // This number is so large that we start losting floating point accuracy.
1439 const int kBigNumber
= 900000000;
1440 // Walk over a range to find floating point inaccuracy boundaries that move
1441 // toward the wrong direction.
1442 const int kRange
= 5000;
1444 for (int i
= 0; i
< kRange
; ++i
) {
1445 scoped_ptr
<LayerImpl
> root
= CreateTestTreeWithOneSurface();
1446 LayerImpl
* child
= root
->children()[0];
1448 gfx::Transform transform
;
1449 transform
.Translate(-kBigNumber
, -kBigNumber
);
1451 // The child layer covers (0, 0, i, i) of the viewport,
1452 // but has a huge negative position.
1453 child
->SetPosition(gfx::PointF());
1454 child
->SetBounds(gfx::Size(kBigNumber
+ i
, kBigNumber
+ i
));
1455 child
->SetContentBounds(gfx::Size(kBigNumber
+ i
, kBigNumber
+ i
));
1456 child
->SetTransform(transform
);
1457 EmulateDrawingOneFrame(root
.get());
1459 // The expected damage should cover the visible part of the child layer,
1460 // which is (0, 0, i, i) in the viewport.
1461 gfx::Rect root_damage_rect
=
1462 root
->render_surface()->damage_tracker()->current_damage_rect();
1463 gfx::Rect damage_we_care_about
= gfx::Rect(i
, i
);
1464 EXPECT_LE(damage_we_care_about
.right(), root_damage_rect
.right());
1465 EXPECT_LE(damage_we_care_about
.bottom(), root_damage_rect
.bottom());