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/test/test_task_graph_runner.h"
16 #include "cc/trees/layer_tree_host_common.h"
17 #include "cc/trees/layer_tree_impl.h"
18 #include "cc/trees/single_thread_proxy.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 #include "third_party/skia/include/effects/SkBlurImageFilter.h"
21 #include "ui/gfx/geometry/quad_f.h"
22 #include "ui/gfx/geometry/rect_conversions.h"
27 void ExecuteCalculateDrawProperties(LayerImpl
* root
,
28 LayerImplList
* render_surface_layer_list
) {
29 // Sanity check: The test itself should create the root layer's render
30 // surface, so that the surface (and its damage tracker) can
31 // persist across multiple calls to this function.
32 ASSERT_TRUE(root
->render_surface());
33 ASSERT_FALSE(render_surface_layer_list
->size());
35 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(root
);
36 LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting
inputs(
37 root
, root
->bounds(), render_surface_layer_list
);
38 LayerTreeHostCommon::CalculateDrawProperties(&inputs
);
41 void ClearDamageForAllSurfaces(LayerImpl
* layer
) {
42 if (layer
->render_surface())
43 layer
->render_surface()->damage_tracker()->DidDrawDamagedArea();
45 // Recursively clear damage for any existing surface.
46 for (size_t i
= 0; i
< layer
->children().size(); ++i
)
47 ClearDamageForAllSurfaces(layer
->children()[i
]);
50 void EmulateDrawingOneFrame(LayerImpl
* root
) {
51 root
->layer_tree_impl()->property_trees()->needs_rebuild
= true;
52 // This emulates only steps that are relevant to testing the damage tracker:
53 // 1. computing the render passes and layerlists
54 // 2. updating all damage trackers in the correct order
55 // 3. resetting all update_rects and property_changed flags for all layers
58 LayerImplList render_surface_layer_list
;
59 ExecuteCalculateDrawProperties(root
, &render_surface_layer_list
);
61 // Iterate back-to-front, so that damage correctly propagates from descendant
62 // surfaces to ancestors.
63 size_t render_surface_layer_list_size
= render_surface_layer_list
.size();
64 for (size_t i
= 0; i
< render_surface_layer_list_size
; ++i
) {
65 size_t index
= render_surface_layer_list_size
- 1 - i
;
66 RenderSurfaceImpl
* target_surface
=
67 render_surface_layer_list
[index
]->render_surface();
68 target_surface
->damage_tracker()->UpdateDamageTrackingState(
69 target_surface
->layer_list(), target_surface
->OwningLayerId(),
70 target_surface
->SurfacePropertyChangedOnlyFromDescendant(),
71 target_surface
->content_rect(),
72 render_surface_layer_list
[index
]->mask_layer(),
73 render_surface_layer_list
[index
]->filters());
76 root
->ResetAllChangeTrackingForSubtree();
79 class DamageTrackerTest
: public testing::Test
{
82 : host_impl_(&proxy_
, &shared_bitmap_manager_
, &task_graph_runner_
) {}
84 scoped_ptr
<LayerImpl
> CreateTestTreeWithOneSurface() {
85 scoped_ptr
<LayerImpl
> root
=
86 LayerImpl::Create(host_impl_
.active_tree(), 1);
87 scoped_ptr
<LayerImpl
> child
=
88 LayerImpl::Create(host_impl_
.active_tree(), 2);
90 root
->SetPosition(gfx::PointF());
91 root
->SetBounds(gfx::Size(500, 500));
92 root
->SetDrawsContent(true);
93 root
->SetHasRenderSurface(true);
94 root
->render_surface()->SetContentRect(gfx::Rect(0, 0, 500, 500));
96 child
->SetPosition(gfx::PointF(100.f
, 100.f
));
97 child
->SetBounds(gfx::Size(30, 30));
98 child
->SetDrawsContent(true);
99 root
->AddChild(child
.Pass());
104 scoped_ptr
<LayerImpl
> CreateTestTreeWithTwoSurfaces() {
105 // This test tree has two render surfaces: one for the root, and one for
106 // child1. Additionally, the root has a second child layer, and child1 has
107 // two children of its own.
109 scoped_ptr
<LayerImpl
> root
=
110 LayerImpl::Create(host_impl_
.active_tree(), 1);
111 scoped_ptr
<LayerImpl
> child1
=
112 LayerImpl::Create(host_impl_
.active_tree(), 2);
113 scoped_ptr
<LayerImpl
> child2
=
114 LayerImpl::Create(host_impl_
.active_tree(), 3);
115 scoped_ptr
<LayerImpl
> grand_child1
=
116 LayerImpl::Create(host_impl_
.active_tree(), 4);
117 scoped_ptr
<LayerImpl
> grand_child2
=
118 LayerImpl::Create(host_impl_
.active_tree(), 5);
120 root
->SetPosition(gfx::PointF());
121 root
->SetBounds(gfx::Size(500, 500));
122 root
->SetDrawsContent(true);
123 root
->SetHasRenderSurface(true);
124 root
->render_surface()->SetContentRect(gfx::Rect(0, 0, 500, 500));
126 child1
->SetPosition(gfx::PointF(100.f
, 100.f
));
127 child1
->SetBounds(gfx::Size(30, 30));
128 // With a child that draws_content, opacity will cause the layer to create
129 // its own RenderSurface. This layer does not draw, but is intended to
130 // create its own RenderSurface.
131 child1
->SetDrawsContent(false);
132 child1
->SetHasRenderSurface(true);
134 child2
->SetPosition(gfx::PointF(11.f
, 11.f
));
135 child2
->SetBounds(gfx::Size(18, 18));
136 child2
->SetDrawsContent(true);
138 grand_child1
->SetPosition(gfx::PointF(200.f
, 200.f
));
139 grand_child1
->SetBounds(gfx::Size(6, 8));
140 grand_child1
->SetDrawsContent(true);
142 grand_child2
->SetPosition(gfx::PointF(190.f
, 190.f
));
143 grand_child2
->SetBounds(gfx::Size(6, 8));
144 grand_child2
->SetDrawsContent(true);
146 child1
->AddChild(grand_child1
.Pass());
147 child1
->AddChild(grand_child2
.Pass());
148 root
->AddChild(child1
.Pass());
149 root
->AddChild(child2
.Pass());
154 scoped_ptr
<LayerImpl
> CreateAndSetUpTestTreeWithOneSurface() {
155 scoped_ptr
<LayerImpl
> root
= CreateTestTreeWithOneSurface();
157 // Setup includes going past the first frame which always damages
158 // everything, so that we can actually perform specific tests.
159 EmulateDrawingOneFrame(root
.get());
164 scoped_ptr
<LayerImpl
> CreateAndSetUpTestTreeWithTwoSurfaces() {
165 scoped_ptr
<LayerImpl
> root
= CreateTestTreeWithTwoSurfaces();
167 // Setup includes going past the first frame which always damages
168 // everything, so that we can actually perform specific tests.
169 EmulateDrawingOneFrame(root
.get());
175 FakeImplProxy proxy_
;
176 TestSharedBitmapManager shared_bitmap_manager_
;
177 TestTaskGraphRunner task_graph_runner_
;
178 FakeLayerTreeHostImpl host_impl_
;
181 TEST_F(DamageTrackerTest
, SanityCheckTestTreeWithOneSurface
) {
182 // Sanity check that the simple test tree will actually produce the expected
183 // render surfaces and layer lists.
185 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
187 EXPECT_EQ(2u, root
->render_surface()->layer_list().size());
188 EXPECT_EQ(1, root
->render_surface()->layer_list()[0]->id());
189 EXPECT_EQ(2, root
->render_surface()->layer_list()[1]->id());
191 gfx::Rect root_damage_rect
=
192 root
->render_surface()->damage_tracker()->current_damage_rect();
194 EXPECT_EQ(gfx::Rect(500, 500).ToString(), root_damage_rect
.ToString());
197 TEST_F(DamageTrackerTest
, SanityCheckTestTreeWithTwoSurfaces
) {
198 // Sanity check that the complex test tree will actually produce the expected
199 // render surfaces and layer lists.
201 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithTwoSurfaces();
203 LayerImpl
* child1
= root
->children()[0];
204 LayerImpl
* child2
= root
->children()[1];
205 gfx::Rect child_damage_rect
=
206 child1
->render_surface()->damage_tracker()->current_damage_rect();
207 gfx::Rect root_damage_rect
=
208 root
->render_surface()->damage_tracker()->current_damage_rect();
210 ASSERT_TRUE(child1
->render_surface());
211 EXPECT_FALSE(child2
->render_surface());
212 EXPECT_EQ(3u, root
->render_surface()->layer_list().size());
213 EXPECT_EQ(2u, child1
->render_surface()->layer_list().size());
215 // The render surface for child1 only has a content_rect that encloses
216 // grand_child1 and grand_child2, because child1 does not draw content.
217 EXPECT_EQ(gfx::Rect(190, 190, 16, 18).ToString(),
218 child_damage_rect
.ToString());
219 EXPECT_EQ(gfx::Rect(500, 500).ToString(), root_damage_rect
.ToString());
222 TEST_F(DamageTrackerTest
, VerifyDamageForUpdateRects
) {
223 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
224 LayerImpl
* child
= root
->children()[0];
226 // CASE 1: Setting the update rect should cause the corresponding damage to
228 ClearDamageForAllSurfaces(root
.get());
229 child
->SetUpdateRect(gfx::Rect(10, 11, 12, 13));
230 EmulateDrawingOneFrame(root
.get());
232 // Damage position on the surface should be: position of update_rect (10, 11)
233 // relative to the child (100, 100).
234 gfx::Rect root_damage_rect
=
235 root
->render_surface()->damage_tracker()->current_damage_rect();
236 EXPECT_EQ(gfx::Rect(110, 111, 12, 13).ToString(),
237 root_damage_rect
.ToString());
239 // CASE 2: The same update rect twice in a row still produces the same
241 ClearDamageForAllSurfaces(root
.get());
242 child
->SetUpdateRect(gfx::Rect(10, 11, 12, 13));
243 EmulateDrawingOneFrame(root
.get());
245 root
->render_surface()->damage_tracker()->current_damage_rect();
246 EXPECT_EQ(gfx::Rect(110, 111, 12, 13).ToString(),
247 root_damage_rect
.ToString());
249 // CASE 3: Setting a different update rect should cause damage on the new
250 // update region, but no additional exposed old region.
251 ClearDamageForAllSurfaces(root
.get());
252 child
->SetUpdateRect(gfx::Rect(20, 25, 1, 2));
253 EmulateDrawingOneFrame(root
.get());
255 // Damage position on the surface should be: position of update_rect (20, 25)
256 // relative to the child (100, 100).
258 root
->render_surface()->damage_tracker()->current_damage_rect();
259 EXPECT_EQ(gfx::Rect(120, 125, 1, 2).ToString(), root_damage_rect
.ToString());
262 TEST_F(DamageTrackerTest
, VerifyDamageForLayerDamageRects
) {
263 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
264 LayerImpl
* child
= root
->children()[0];
266 // CASE 1: Adding the layer damage rect should cause the corresponding damage
268 ClearDamageForAllSurfaces(root
.get());
269 child
->AddDamageRect(gfx::Rect(10, 11, 12, 13));
270 EmulateDrawingOneFrame(root
.get());
272 // Damage position on the surface should be: position of layer damage_rect
273 // (10, 11) relative to the child (100, 100).
274 gfx::Rect root_damage_rect
=
275 root
->render_surface()->damage_tracker()->current_damage_rect();
276 EXPECT_EQ(true, root_damage_rect
.Contains(gfx::Rect(110, 111, 12, 13)));
278 // CASE 2: The same layer damage rect twice in a row still produces the same
280 ClearDamageForAllSurfaces(root
.get());
281 child
->AddDamageRect(gfx::Rect(10, 11, 12, 13));
282 EmulateDrawingOneFrame(root
.get());
284 root
->render_surface()->damage_tracker()->current_damage_rect();
285 EXPECT_EQ(true, root_damage_rect
.Contains(gfx::Rect(110, 111, 12, 13)));
287 // CASE 3: Adding a different layer damage rect should cause damage on the
288 // new damaged region, but no additional exposed old region.
289 ClearDamageForAllSurfaces(root
.get());
290 child
->AddDamageRect(gfx::Rect(20, 25, 1, 2));
291 EmulateDrawingOneFrame(root
.get());
293 // Damage position on the surface should be: position of layer damage_rect
294 // (20, 25) relative to the child (100, 100).
296 root
->render_surface()->damage_tracker()->current_damage_rect();
297 EXPECT_EQ(true, root_damage_rect
.Contains(gfx::Rect(120, 125, 1, 2)));
299 // CASE 4: Adding multiple layer damage rects should cause a unified
300 // damage on root damage rect.
301 ClearDamageForAllSurfaces(root
.get());
302 child
->AddDamageRect(gfx::Rect(20, 25, 1, 2));
303 child
->AddDamageRect(gfx::Rect(10, 15, 3, 4));
304 EmulateDrawingOneFrame(root
.get());
306 // Damage position on the surface should be: position of layer damage_rect
307 // (20, 25) relative to the child (100, 100).
309 root
->render_surface()->damage_tracker()->current_damage_rect();
310 EXPECT_EQ(true, root_damage_rect
.Contains(gfx::Rect(120, 125, 1, 2)));
311 EXPECT_EQ(true, root_damage_rect
.Contains(gfx::Rect(110, 115, 3, 4)));
314 TEST_F(DamageTrackerTest
, VerifyDamageForLayerUpdateAndDamageRects
) {
315 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
316 LayerImpl
* child
= root
->children()[0];
318 // CASE 1: Adding the layer damage rect and update rect should cause the
319 // corresponding damage to the surface.
320 ClearDamageForAllSurfaces(root
.get());
321 child
->AddDamageRect(gfx::Rect(5, 6, 12, 13));
322 child
->SetUpdateRect(gfx::Rect(15, 16, 14, 10));
323 EmulateDrawingOneFrame(root
.get());
325 // Damage position on the surface should be: position of unified layer
326 // damage_rect and update rect (5, 6)
327 // relative to the child (100, 100).
328 gfx::Rect root_damage_rect
=
329 root
->render_surface()->damage_tracker()->current_damage_rect();
330 EXPECT_EQ(true, root_damage_rect
.Contains(gfx::Rect(105, 106, 24, 20)));
332 // CASE 2: The same layer damage rect and update rect twice in a row still
333 // produces the same damage.
334 ClearDamageForAllSurfaces(root
.get());
335 child
->AddDamageRect(gfx::Rect(10, 11, 12, 13));
336 child
->SetUpdateRect(gfx::Rect(10, 11, 14, 15));
337 EmulateDrawingOneFrame(root
.get());
339 root
->render_surface()->damage_tracker()->current_damage_rect();
340 EXPECT_EQ(true, root_damage_rect
.Contains(gfx::Rect(110, 111, 14, 15)));
342 // CASE 3: Adding a different layer damage rect and update rect should cause
343 // damage on the new damaged region, but no additional exposed old region.
344 ClearDamageForAllSurfaces(root
.get());
345 child
->AddDamageRect(gfx::Rect(20, 25, 2, 3));
346 child
->SetUpdateRect(gfx::Rect(5, 10, 7, 8));
347 EmulateDrawingOneFrame(root
.get());
349 // Damage position on the surface should be: position of unified layer damage
350 // rect and update rect (5, 10) relative to the child (100, 100).
352 root
->render_surface()->damage_tracker()->current_damage_rect();
353 EXPECT_EQ(true, root_damage_rect
.Contains(gfx::Rect(105, 110, 17, 18)));
356 TEST_F(DamageTrackerTest
, VerifyDamageForPropertyChanges
) {
357 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
358 LayerImpl
* child
= root
->children()[0];
360 // CASE 1: The layer's property changed flag takes priority over update rect.
362 ClearDamageForAllSurfaces(root
.get());
363 child
->SetUpdateRect(gfx::Rect(10, 11, 12, 13));
364 child
->SetOpacity(0.5f
);
365 EmulateDrawingOneFrame(root
.get());
367 // Sanity check - we should not have accidentally created a separate render
368 // surface for the translucent layer.
369 ASSERT_FALSE(child
->render_surface());
370 ASSERT_EQ(2u, root
->render_surface()->layer_list().size());
372 // Damage should be the entire child layer in target_surface space.
373 gfx::Rect expected_rect
= gfx::Rect(100, 100, 30, 30);
374 gfx::Rect root_damage_rect
=
375 root
->render_surface()->damage_tracker()->current_damage_rect();
376 EXPECT_EQ(expected_rect
.ToString(), root_damage_rect
.ToString());
378 // CASE 2: If a layer moves due to property change, it damages both the new
379 // location and the old (exposed) location. The old location is the
380 // entire old layer, not just the update_rect.
382 // Cycle one frame of no change, just to sanity check that the next rect is
383 // not because of the old damage state.
384 ClearDamageForAllSurfaces(root
.get());
385 EmulateDrawingOneFrame(root
.get());
387 root
->render_surface()->damage_tracker()->current_damage_rect();
388 EXPECT_TRUE(root_damage_rect
.IsEmpty());
390 // Then, test the actual layer movement.
391 ClearDamageForAllSurfaces(root
.get());
392 child
->SetPosition(gfx::PointF(200.f
, 230.f
));
393 EmulateDrawingOneFrame(root
.get());
395 // Expect damage to be the combination of the previous one and the new one.
396 expected_rect
.Union(gfx::Rect(200, 230, 30, 30));
398 root
->render_surface()->damage_tracker()->current_damage_rect();
399 EXPECT_FLOAT_RECT_EQ(expected_rect
, root_damage_rect
);
402 TEST_F(DamageTrackerTest
, VerifyDamageForTransformedLayer
) {
403 // If a layer is transformed, the damage rect should still enclose the entire
404 // transformed layer.
406 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
407 LayerImpl
* child
= root
->children()[0];
409 gfx::Transform rotation
;
410 rotation
.Rotate(45.0);
412 ClearDamageForAllSurfaces(root
.get());
413 child
->SetTransformOrigin(gfx::Point3F(
414 child
->bounds().width() * 0.5f
, child
->bounds().height() * 0.5f
, 0.f
));
415 child
->SetPosition(gfx::PointF(85.f
, 85.f
));
416 EmulateDrawingOneFrame(root
.get());
418 // Sanity check that the layer actually moved to (85, 85), damaging its old
419 // location and new location.
420 gfx::Rect root_damage_rect
=
421 root
->render_surface()->damage_tracker()->current_damage_rect();
422 EXPECT_EQ(gfx::Rect(85, 85, 45, 45).ToString(), root_damage_rect
.ToString());
424 // With the anchor on the layer's center, now we can test the rotation more
425 // intuitively, since it applies about the layer's anchor.
426 ClearDamageForAllSurfaces(root
.get());
427 child
->SetTransform(rotation
);
428 EmulateDrawingOneFrame(root
.get());
430 // Since the child layer is square, rotation by 45 degrees about the center
431 // should increase the size of the expected rect by sqrt(2), centered around
432 // (100, 100). The old exposed region should be fully contained in the new
434 float expected_width
= 30.f
* sqrt(2.f
);
435 float expected_position
= 100.f
- 0.5f
* expected_width
;
436 gfx::Rect expected_rect
= gfx::ToEnclosingRect(gfx::RectF(
437 expected_position
, expected_position
, expected_width
, expected_width
));
439 root
->render_surface()->damage_tracker()->current_damage_rect();
440 EXPECT_EQ(expected_rect
.ToString(), root_damage_rect
.ToString());
443 TEST_F(DamageTrackerTest
, VerifyDamageForPerspectiveClippedLayer
) {
444 // If a layer has a perspective transform that causes w < 0, then not
445 // clipping the layer can cause an invalid damage rect. This test checks that
446 // the w < 0 case is tracked properly.
448 // The transform is constructed so that if w < 0 clipping is not performed,
449 // the incorrect rect will be very small, specifically: position (500.972504,
450 // 498.544617) and size 0.056610 x 2.910767. Instead, the correctly
451 // transformed rect should actually be very huge (i.e. in theory, -infinity
452 // on the left), and positioned so that the right-most bound rect will be
453 // approximately 501 units in root surface space.
456 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
457 LayerImpl
* child
= root
->children()[0];
459 gfx::Transform transform
;
460 transform
.Translate3d(500.0, 500.0, 0.0);
461 transform
.ApplyPerspectiveDepth(1.0);
462 transform
.RotateAboutYAxis(45.0);
463 transform
.Translate3d(-50.0, -50.0, 0.0);
466 child
->SetPosition(gfx::PointF(0.f
, 0.f
));
467 child
->SetBounds(gfx::Size(100, 100));
468 child
->SetTransform(transform
);
469 EmulateDrawingOneFrame(root
.get());
471 // Sanity check that the child layer's bounds would actually get clipped by
472 // w < 0, otherwise this test is not actually testing the intended scenario.
473 gfx::QuadF
test_quad(gfx::RectF(gfx::PointF(), gfx::SizeF(100.f
, 100.f
)));
474 bool clipped
= false;
475 MathUtil::MapQuad(transform
, test_quad
, &clipped
);
476 EXPECT_TRUE(clipped
);
478 // Damage the child without moving it.
479 ClearDamageForAllSurfaces(root
.get());
480 child
->SetOpacity(0.5f
);
481 EmulateDrawingOneFrame(root
.get());
483 // The expected damage should cover the entire root surface (500x500), but we
484 // don't care whether the damage rect was clamped or is larger than the
485 // surface for this test.
486 gfx::Rect root_damage_rect
=
487 root
->render_surface()->damage_tracker()->current_damage_rect();
488 gfx::Rect damage_we_care_about
= gfx::Rect(gfx::Size(500, 500));
489 EXPECT_TRUE(root_damage_rect
.Contains(damage_we_care_about
));
492 TEST_F(DamageTrackerTest
, VerifyDamageForBlurredSurface
) {
493 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithTwoSurfaces();
494 LayerImpl
* surface
= root
->children()[0];
495 LayerImpl
* child
= surface
->children()[0];
497 FilterOperations filters
;
498 filters
.Append(FilterOperation::CreateBlurFilter(5.f
));
499 int outset_top
, outset_right
, outset_bottom
, outset_left
;
500 filters
.GetOutsets(&outset_top
, &outset_right
, &outset_bottom
, &outset_left
);
502 // Setting the filter will damage the whole surface.
503 ClearDamageForAllSurfaces(root
.get());
504 surface
->SetFilters(filters
);
505 EmulateDrawingOneFrame(root
.get());
507 // Setting the update rect should cause the corresponding damage to the
508 // surface, blurred based on the size of the blur filter.
509 ClearDamageForAllSurfaces(root
.get());
510 child
->SetUpdateRect(gfx::Rect(1, 2, 3, 4));
511 EmulateDrawingOneFrame(root
.get());
513 // Damage position on the surface should be: position of update_rect (1, 2)
514 // relative to the child (300, 300), but expanded by the blur outsets.
515 gfx::Rect root_damage_rect
=
516 root
->render_surface()->damage_tracker()->current_damage_rect();
517 gfx::Rect expected_damage_rect
= gfx::Rect(301, 302, 3, 4);
519 expected_damage_rect
.Inset(-outset_left
,
523 EXPECT_EQ(expected_damage_rect
.ToString(), root_damage_rect
.ToString());
526 TEST_F(DamageTrackerTest
, VerifyDamageForImageFilter
) {
527 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
528 LayerImpl
* child
= root
->children()[0];
529 gfx::Rect root_damage_rect
, child_damage_rect
;
531 // Allow us to set damage on child too.
532 child
->SetDrawsContent(true);
534 skia::RefPtr
<SkImageFilter
> filter
= skia::AdoptRef(
535 SkBlurImageFilter::Create(SkIntToScalar(2), SkIntToScalar(2)));
536 FilterOperations filters
;
537 filters
.Append(FilterOperation::CreateReferenceFilter(filter
));
538 int outset_top
, outset_right
, outset_bottom
, outset_left
;
539 filters
.GetOutsets(&outset_top
, &outset_right
, &outset_bottom
, &outset_left
);
541 // Setting the filter will damage the whole surface.
542 ClearDamageForAllSurfaces(root
.get());
543 child
->SetHasRenderSurface(true);
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());
553 gfx::Rect(-outset_left
, -outset_top
, 30 + (outset_left
+ outset_right
),
554 30 + (outset_top
+ outset_bottom
))
556 child_damage_rect
.ToString());
558 // CASE 1: Setting the update rect should damage the whole surface (for now)
559 ClearDamageForAllSurfaces(root
.get());
560 child
->SetUpdateRect(gfx::Rect(1, 1));
561 EmulateDrawingOneFrame(root
.get());
564 root
->render_surface()->damage_tracker()->current_damage_rect();
566 child
->render_surface()->damage_tracker()->current_damage_rect();
568 int expect_width
= 1 + outset_left
+ outset_right
;
569 int expect_height
= 1 + outset_top
+ outset_bottom
;
570 EXPECT_EQ(gfx::Rect(100 - outset_left
, 100 - outset_top
, expect_width
,
573 root_damage_rect
.ToString());
574 EXPECT_EQ(gfx::Rect(-outset_left
, -outset_top
, expect_width
, expect_height
)
576 child_damage_rect
.ToString());
579 TEST_F(DamageTrackerTest
, VerifyDamageForBackgroundBlurredChild
) {
580 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithTwoSurfaces();
581 LayerImpl
* child1
= root
->children()[0];
582 LayerImpl
* child2
= root
->children()[1];
584 // Allow us to set damage on child1 too.
585 child1
->SetDrawsContent(true);
587 FilterOperations filters
;
588 filters
.Append(FilterOperation::CreateBlurFilter(2.f
));
589 int outset_top
, outset_right
, outset_bottom
, outset_left
;
590 filters
.GetOutsets(&outset_top
, &outset_right
, &outset_bottom
, &outset_left
);
592 // Setting the filter will damage the whole surface.
593 ClearDamageForAllSurfaces(root
.get());
594 child1
->SetBackgroundFilters(filters
);
595 EmulateDrawingOneFrame(root
.get());
597 // CASE 1: Setting the update rect should cause the corresponding damage to
598 // the surface, blurred based on the size of the child's background
600 ClearDamageForAllSurfaces(root
.get());
601 root
->SetUpdateRect(gfx::Rect(297, 297, 2, 2));
602 EmulateDrawingOneFrame(root
.get());
604 gfx::Rect root_damage_rect
=
605 root
->render_surface()->damage_tracker()->current_damage_rect();
606 // Damage position on the surface should be a composition of the damage on
607 // the root and on child2. Damage on the root should be: position of
608 // update_rect (297, 297), but expanded by the blur outsets.
609 gfx::Rect expected_damage_rect
= gfx::Rect(297, 297, 2, 2);
611 expected_damage_rect
.Inset(-outset_left
,
615 EXPECT_EQ(expected_damage_rect
.ToString(), root_damage_rect
.ToString());
617 // CASE 2: Setting the update rect should cause the corresponding damage to
618 // the surface, blurred based on the size of the child's background
619 // blur filter. Since the damage extends to the right/bottom outside
620 // of the blurred layer, only the left/top should end up expanded.
621 ClearDamageForAllSurfaces(root
.get());
622 root
->SetUpdateRect(gfx::Rect(297, 297, 30, 30));
623 EmulateDrawingOneFrame(root
.get());
626 root
->render_surface()->damage_tracker()->current_damage_rect();
627 // Damage position on the surface should be a composition of the damage on
628 // the root and on child2. Damage on the root should be: position of
629 // update_rect (297, 297), but expanded on the left/top by the blur outsets.
630 expected_damage_rect
= gfx::Rect(297, 297, 30, 30);
632 expected_damage_rect
.Inset(-outset_left
,
636 EXPECT_EQ(expected_damage_rect
.ToString(), root_damage_rect
.ToString());
638 // CASE 3: Setting this update rect outside the blurred content_bounds of the
639 // blurred child1 will not cause it to be expanded.
640 ClearDamageForAllSurfaces(root
.get());
641 root
->SetUpdateRect(gfx::Rect(30, 30, 2, 2));
642 EmulateDrawingOneFrame(root
.get());
645 root
->render_surface()->damage_tracker()->current_damage_rect();
646 // Damage on the root should be: position of update_rect (30, 30), not
648 expected_damage_rect
= gfx::Rect(30, 30, 2, 2);
650 EXPECT_EQ(expected_damage_rect
.ToString(), root_damage_rect
.ToString());
652 // CASE 4: Setting this update rect inside the blurred content_bounds but
653 // outside the original content_bounds of the blurred child1 will
654 // cause it to be expanded.
655 ClearDamageForAllSurfaces(root
.get());
656 root
->SetUpdateRect(gfx::Rect(99, 99, 1, 1));
657 EmulateDrawingOneFrame(root
.get());
660 root
->render_surface()->damage_tracker()->current_damage_rect();
661 // Damage on the root should be: position of update_rect (99, 99), expanded by
662 // the blurring on child1, but since it is 1 pixel outside the layer, the
663 // expanding should be reduced by 1.
664 expected_damage_rect
= gfx::Rect(99, 99, 1, 1);
666 expected_damage_rect
.Inset(-outset_left
+ 1,
670 EXPECT_EQ(expected_damage_rect
.ToString(), root_damage_rect
.ToString());
672 // CASE 5: Setting the update rect on child2, which is above child1, will
673 // not get blurred by child1, so it does not need to get expanded.
674 ClearDamageForAllSurfaces(root
.get());
675 child2
->SetUpdateRect(gfx::Rect(1, 1));
676 EmulateDrawingOneFrame(root
.get());
679 root
->render_surface()->damage_tracker()->current_damage_rect();
680 // Damage on child2 should be: position of update_rect offset by the child's
681 // position (11, 11), and not expanded by anything.
682 expected_damage_rect
= gfx::Rect(11, 11, 1, 1);
684 EXPECT_EQ(expected_damage_rect
.ToString(), root_damage_rect
.ToString());
686 // CASE 6: Setting the update rect on child1 will also blur the damage, so
687 // that any pixels needed for the blur are redrawn in the current
689 ClearDamageForAllSurfaces(root
.get());
690 child1
->SetUpdateRect(gfx::Rect(1, 1));
691 EmulateDrawingOneFrame(root
.get());
694 root
->render_surface()->damage_tracker()->current_damage_rect();
695 // Damage on child1 should be: position of update_rect offset by the child's
696 // position (100, 100), and expanded by the damage.
697 expected_damage_rect
= gfx::Rect(100, 100, 1, 1);
699 expected_damage_rect
.Inset(-outset_left
,
703 EXPECT_EQ(expected_damage_rect
.ToString(), root_damage_rect
.ToString());
706 TEST_F(DamageTrackerTest
, VerifyDamageForAddingAndRemovingLayer
) {
707 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
708 LayerImpl
* child1
= root
->children()[0];
710 // CASE 1: Adding a new layer should cause the appropriate damage.
712 ClearDamageForAllSurfaces(root
.get());
714 scoped_ptr
<LayerImpl
> child2
=
715 LayerImpl::Create(host_impl_
.active_tree(), 3);
716 child2
->SetPosition(gfx::PointF(400.f
, 380.f
));
717 child2
->SetBounds(gfx::Size(6, 8));
718 child2
->SetDrawsContent(true);
719 root
->AddChild(child2
.Pass());
721 EmulateDrawingOneFrame(root
.get());
723 // Sanity check - all 3 layers should be on the same render surface; render
724 // surfaces are tested elsewhere.
725 ASSERT_EQ(3u, root
->render_surface()->layer_list().size());
727 gfx::Rect root_damage_rect
=
728 root
->render_surface()->damage_tracker()->current_damage_rect();
729 EXPECT_EQ(gfx::Rect(400, 380, 6, 8).ToString(), root_damage_rect
.ToString());
731 // CASE 2: If the layer is removed, its entire old layer becomes exposed, not
732 // just the last update rect.
734 // Advance one frame without damage so that we know the damage rect is not
735 // leftover from the previous case.
736 ClearDamageForAllSurfaces(root
.get());
737 EmulateDrawingOneFrame(root
.get());
740 root
->render_surface()->damage_tracker()->current_damage_rect();
741 EXPECT_TRUE(root_damage_rect
.IsEmpty());
743 // Then, test removing child1.
744 root
->RemoveChild(child1
);
746 EmulateDrawingOneFrame(root
.get());
749 root
->render_surface()->damage_tracker()->current_damage_rect();
750 EXPECT_EQ(gfx::Rect(100, 100, 30, 30).ToString(),
751 root_damage_rect
.ToString());
754 TEST_F(DamageTrackerTest
, VerifyDamageForNewUnchangedLayer
) {
755 // If child2 is added to the layer tree, but it doesn't have any explicit
756 // damage of its own, it should still indeed damage the target surface.
758 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
760 ClearDamageForAllSurfaces(root
.get());
762 scoped_ptr
<LayerImpl
> child2
=
763 LayerImpl::Create(host_impl_
.active_tree(), 3);
764 child2
->SetPosition(gfx::PointF(400.f
, 380.f
));
765 child2
->SetBounds(gfx::Size(6, 8));
766 child2
->SetDrawsContent(true);
767 child2
->ResetAllChangeTrackingForSubtree();
768 // Sanity check the initial conditions of the test, if these asserts
769 // trigger, it means the test no longer actually covers the intended
771 ASSERT_FALSE(child2
->LayerPropertyChanged());
772 ASSERT_TRUE(child2
->update_rect().IsEmpty());
773 root
->AddChild(child2
.Pass());
775 EmulateDrawingOneFrame(root
.get());
777 // Sanity check - all 3 layers should be on the same render surface; render
778 // surfaces are tested elsewhere.
779 ASSERT_EQ(3u, root
->render_surface()->layer_list().size());
781 gfx::Rect root_damage_rect
=
782 root
->render_surface()->damage_tracker()->current_damage_rect();
783 EXPECT_EQ(gfx::Rect(400, 380, 6, 8).ToString(), root_damage_rect
.ToString());
786 TEST_F(DamageTrackerTest
, VerifyDamageForMultipleLayers
) {
787 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
788 LayerImpl
* child1
= root
->children()[0];
790 // In this test we don't want the above tree manipulation to be considered
791 // part of the same frame.
792 ClearDamageForAllSurfaces(root
.get());
794 scoped_ptr
<LayerImpl
> child2
=
795 LayerImpl::Create(host_impl_
.active_tree(), 3);
796 child2
->SetPosition(gfx::PointF(400.f
, 380.f
));
797 child2
->SetBounds(gfx::Size(6, 8));
798 child2
->SetDrawsContent(true);
799 root
->AddChild(child2
.Pass());
801 LayerImpl
* child2
= root
->children()[1];
802 EmulateDrawingOneFrame(root
.get());
804 // Damaging two layers simultaneously should cause combined damage.
805 // - child1 update rect in surface space: gfx::Rect(100, 100, 1, 2);
806 // - child2 update rect in surface space: gfx::Rect(400, 380, 3, 4);
807 ClearDamageForAllSurfaces(root
.get());
808 child1
->SetUpdateRect(gfx::Rect(1, 2));
809 child2
->SetUpdateRect(gfx::Rect(3, 4));
810 EmulateDrawingOneFrame(root
.get());
811 gfx::Rect root_damage_rect
=
812 root
->render_surface()->damage_tracker()->current_damage_rect();
813 EXPECT_EQ(gfx::Rect(100, 100, 303, 284).ToString(),
814 root_damage_rect
.ToString());
817 TEST_F(DamageTrackerTest
, VerifyDamageForNestedSurfaces
) {
818 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithTwoSurfaces();
819 LayerImpl
* child1
= root
->children()[0];
820 LayerImpl
* child2
= root
->children()[1];
821 LayerImpl
* grand_child1
= root
->children()[0]->children()[0];
822 gfx::Rect child_damage_rect
;
823 gfx::Rect root_damage_rect
;
825 // CASE 1: Damage to a descendant surface should propagate properly to
827 ClearDamageForAllSurfaces(root
.get());
828 grand_child1
->SetOpacity(0.5f
);
829 EmulateDrawingOneFrame(root
.get());
831 child1
->render_surface()->damage_tracker()->current_damage_rect();
833 root
->render_surface()->damage_tracker()->current_damage_rect();
834 EXPECT_EQ(gfx::Rect(200, 200, 6, 8).ToString(), child_damage_rect
.ToString());
835 EXPECT_EQ(gfx::Rect(300, 300, 6, 8).ToString(), root_damage_rect
.ToString());
837 // CASE 2: Same as previous case, but with additional damage elsewhere that
838 // should be properly unioned.
839 // - child1 surface damage in root surface space:
840 // gfx::Rect(300, 300, 6, 8);
841 // - child2 damage in root surface space:
842 // gfx::Rect(11, 11, 18, 18);
843 ClearDamageForAllSurfaces(root
.get());
844 grand_child1
->SetOpacity(0.7f
);
845 child2
->SetOpacity(0.7f
);
846 EmulateDrawingOneFrame(root
.get());
848 child1
->render_surface()->damage_tracker()->current_damage_rect();
850 root
->render_surface()->damage_tracker()->current_damage_rect();
851 EXPECT_EQ(gfx::Rect(200, 200, 6, 8).ToString(), child_damage_rect
.ToString());
852 EXPECT_EQ(gfx::Rect(11, 11, 295, 297).ToString(),
853 root_damage_rect
.ToString());
856 TEST_F(DamageTrackerTest
, VerifyDamageForSurfaceChangeFromDescendantLayer
) {
857 // If descendant layer changes and affects the content bounds of the render
858 // surface, then the entire descendant surface should be damaged, and it
859 // should damage its ancestor surface with the old and new surface regions.
861 // This is a tricky case, since only the first grand_child changes, but the
862 // entire surface should be marked dirty.
864 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithTwoSurfaces();
865 LayerImpl
* child1
= root
->children()[0];
866 LayerImpl
* grand_child1
= root
->children()[0]->children()[0];
867 gfx::Rect child_damage_rect
;
868 gfx::Rect root_damage_rect
;
870 ClearDamageForAllSurfaces(root
.get());
871 grand_child1
->SetPosition(gfx::PointF(195.f
, 205.f
));
872 EmulateDrawingOneFrame(root
.get());
874 child1
->render_surface()->damage_tracker()->current_damage_rect();
876 root
->render_surface()->damage_tracker()->current_damage_rect();
878 // The new surface bounds should be damaged entirely, even though only one of
879 // the layers changed.
880 EXPECT_EQ(gfx::Rect(190, 190, 11, 23).ToString(),
881 child_damage_rect
.ToString());
883 // Damage to the root surface should be the union of child1's *entire* render
884 // surface (in target space), and its old exposed area (also in target
886 EXPECT_EQ(gfx::Rect(290, 290, 16, 23).ToString(),
887 root_damage_rect
.ToString());
890 TEST_F(DamageTrackerTest
, VerifyDamageForSurfaceChangeFromAncestorLayer
) {
891 // An ancestor/owning layer changes that affects the position/transform of
892 // the render surface. Note that in this case, the layer_property_changed flag
893 // already propagates to the subtree (tested in LayerImpltest), which damages
894 // the entire child1 surface, but the damage tracker still needs the correct
895 // logic to compute the exposed region on the root surface.
897 // TODO(shawnsingh): the expectations of this test case should change when we
898 // add support for a unique scissor_rect per RenderSurface. In that case, the
899 // child1 surface should be completely unchanged, since we are only
900 // transforming it, while the root surface would be damaged appropriately.
902 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithTwoSurfaces();
903 LayerImpl
* child1
= root
->children()[0];
904 gfx::Rect child_damage_rect
;
905 gfx::Rect root_damage_rect
;
907 ClearDamageForAllSurfaces(root
.get());
908 child1
->SetPosition(gfx::PointF(50.f
, 50.f
));
909 EmulateDrawingOneFrame(root
.get());
911 child1
->render_surface()->damage_tracker()->current_damage_rect();
913 root
->render_surface()->damage_tracker()->current_damage_rect();
915 // The new surface bounds should be damaged entirely.
916 EXPECT_EQ(gfx::Rect(190, 190, 16, 18).ToString(),
917 child_damage_rect
.ToString());
919 // The entire child1 surface and the old exposed child1 surface should damage
921 // - old child1 surface in target space: gfx::Rect(290, 290, 16, 18)
922 // - new child1 surface in target space: gfx::Rect(240, 240, 16, 18)
923 EXPECT_EQ(gfx::Rect(240, 240, 66, 68).ToString(),
924 root_damage_rect
.ToString());
927 TEST_F(DamageTrackerTest
, VerifyDamageForAddingAndRemovingRenderSurfaces
) {
928 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithTwoSurfaces();
929 LayerImpl
* child1
= root
->children()[0];
930 gfx::Rect child_damage_rect
;
931 gfx::Rect root_damage_rect
;
933 // CASE 1: If a descendant surface disappears, its entire old area becomes
935 ClearDamageForAllSurfaces(root
.get());
936 child1
->SetHasRenderSurface(false);
937 EmulateDrawingOneFrame(root
.get());
939 // Sanity check that there is only one surface now.
940 ASSERT_FALSE(child1
->render_surface());
941 ASSERT_EQ(4u, root
->render_surface()->layer_list().size());
944 root
->render_surface()->damage_tracker()->current_damage_rect();
945 EXPECT_EQ(gfx::Rect(290, 290, 16, 18).ToString(),
946 root_damage_rect
.ToString());
948 // CASE 2: If a descendant surface appears, its entire old area becomes
951 // Cycle one frame of no change, just to sanity check that the next rect is
952 // not because of the old damage state.
953 ClearDamageForAllSurfaces(root
.get());
954 EmulateDrawingOneFrame(root
.get());
956 root
->render_surface()->damage_tracker()->current_damage_rect();
957 EXPECT_TRUE(root_damage_rect
.IsEmpty());
959 // Then change the tree so that the render surface is added back.
960 ClearDamageForAllSurfaces(root
.get());
961 child1
->SetHasRenderSurface(true);
963 EmulateDrawingOneFrame(root
.get());
965 // Sanity check that there is a new surface now.
966 ASSERT_TRUE(child1
->render_surface());
967 EXPECT_EQ(3u, root
->render_surface()->layer_list().size());
968 EXPECT_EQ(2u, child1
->render_surface()->layer_list().size());
971 child1
->render_surface()->damage_tracker()->current_damage_rect();
973 root
->render_surface()->damage_tracker()->current_damage_rect();
974 EXPECT_EQ(gfx::Rect(190, 190, 16, 18).ToString(),
975 child_damage_rect
.ToString());
976 EXPECT_EQ(gfx::Rect(290, 290, 16, 18).ToString(),
977 root_damage_rect
.ToString());
980 TEST_F(DamageTrackerTest
, VerifyNoDamageWhenNothingChanged
) {
981 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithTwoSurfaces();
982 LayerImpl
* child1
= root
->children()[0];
983 gfx::Rect child_damage_rect
;
984 gfx::Rect root_damage_rect
;
986 // CASE 1: If nothing changes, the damage rect should be empty.
988 ClearDamageForAllSurfaces(root
.get());
989 EmulateDrawingOneFrame(root
.get());
991 child1
->render_surface()->damage_tracker()->current_damage_rect();
993 root
->render_surface()->damage_tracker()->current_damage_rect();
994 EXPECT_TRUE(child_damage_rect
.IsEmpty());
995 EXPECT_TRUE(root_damage_rect
.IsEmpty());
997 // CASE 2: If nothing changes twice in a row, the damage rect should still be
1000 ClearDamageForAllSurfaces(root
.get());
1001 EmulateDrawingOneFrame(root
.get());
1003 child1
->render_surface()->damage_tracker()->current_damage_rect();
1005 root
->render_surface()->damage_tracker()->current_damage_rect();
1006 EXPECT_TRUE(child_damage_rect
.IsEmpty());
1007 EXPECT_TRUE(root_damage_rect
.IsEmpty());
1010 TEST_F(DamageTrackerTest
, VerifyNoDamageForUpdateRectThatDoesNotDrawContent
) {
1011 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithTwoSurfaces();
1012 LayerImpl
* child1
= root
->children()[0];
1013 gfx::Rect child_damage_rect
;
1014 gfx::Rect root_damage_rect
;
1016 // In our specific tree, the update rect of child1 should not cause any
1017 // damage to any surface because it does not actually draw content.
1018 ClearDamageForAllSurfaces(root
.get());
1019 child1
->SetUpdateRect(gfx::Rect(1, 2));
1020 EmulateDrawingOneFrame(root
.get());
1022 child1
->render_surface()->damage_tracker()->current_damage_rect();
1024 root
->render_surface()->damage_tracker()->current_damage_rect();
1025 EXPECT_TRUE(child_damage_rect
.IsEmpty());
1026 EXPECT_TRUE(root_damage_rect
.IsEmpty());
1029 TEST_F(DamageTrackerTest
, VerifyDamageForReplica
) {
1030 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithTwoSurfaces();
1031 LayerImpl
* child1
= root
->children()[0];
1032 LayerImpl
* grand_child1
= child1
->children()[0];
1033 LayerImpl
* grand_child2
= child1
->children()[1];
1035 // Damage on a surface that has a reflection should cause the target surface
1036 // to receive the surface's damage and the surface's reflected damage.
1038 // For this test case, we modify grand_child2, and add grand_child3 to extend
1039 // the bounds of child1's surface. This way, we can test reflection changes
1040 // without changing content_bounds of the surface.
1041 grand_child2
->SetPosition(gfx::PointF(180.f
, 180.f
));
1043 scoped_ptr
<LayerImpl
> grand_child3
=
1044 LayerImpl::Create(host_impl_
.active_tree(), 6);
1045 grand_child3
->SetPosition(gfx::PointF(240.f
, 240.f
));
1046 grand_child3
->SetBounds(gfx::Size(10, 10));
1047 grand_child3
->SetDrawsContent(true);
1048 child1
->AddChild(grand_child3
.Pass());
1050 child1
->SetOpacity(0.5f
);
1051 EmulateDrawingOneFrame(root
.get());
1053 // CASE 1: adding a reflection about the left edge of grand_child1.
1055 ClearDamageForAllSurfaces(root
.get());
1057 scoped_ptr
<LayerImpl
> grand_child1_replica
=
1058 LayerImpl::Create(host_impl_
.active_tree(), 7);
1059 grand_child1_replica
->SetPosition(gfx::PointF());
1060 gfx::Transform reflection
;
1061 reflection
.Scale3d(-1.0, 1.0, 1.0);
1062 grand_child1_replica
->SetTransform(reflection
);
1063 grand_child1
->SetReplicaLayer(grand_child1_replica
.Pass());
1064 grand_child1
->SetHasRenderSurface(true);
1066 EmulateDrawingOneFrame(root
.get());
1068 gfx::Rect grand_child_damage_rect
=
1069 grand_child1
->render_surface()->damage_tracker()->current_damage_rect();
1070 gfx::Rect child_damage_rect
=
1071 child1
->render_surface()->damage_tracker()->current_damage_rect();
1072 gfx::Rect root_damage_rect
=
1073 root
->render_surface()->damage_tracker()->current_damage_rect();
1075 // The grand_child surface damage should not include its own replica. The
1076 // child surface damage should include the normal and replica surfaces.
1077 EXPECT_EQ(gfx::Rect(6, 8).ToString(), grand_child_damage_rect
.ToString());
1078 EXPECT_EQ(gfx::Rect(194, 200, 12, 8).ToString(),
1079 child_damage_rect
.ToString());
1080 EXPECT_EQ(gfx::Rect(294, 300, 12, 8).ToString(), root_damage_rect
.ToString());
1082 // CASE 2: moving the descendant surface should cause both the original and
1083 // reflected areas to be damaged on the target.
1084 ClearDamageForAllSurfaces(root
.get());
1085 gfx::Rect old_content_rect
= child1
->render_surface()->content_rect();
1086 grand_child1
->SetPosition(gfx::PointF(195.f
, 205.f
));
1087 EmulateDrawingOneFrame(root
.get());
1088 ASSERT_EQ(old_content_rect
.width(),
1089 child1
->render_surface()->content_rect().width());
1090 ASSERT_EQ(old_content_rect
.height(),
1091 child1
->render_surface()->content_rect().height());
1093 grand_child_damage_rect
=
1094 grand_child1
->render_surface()->
1095 damage_tracker()->current_damage_rect();
1097 child1
->render_surface()->damage_tracker()->current_damage_rect();
1099 root
->render_surface()->damage_tracker()->current_damage_rect();
1101 // The child surface damage should include normal and replica surfaces for
1102 // both old and new locations.
1103 // - old location in target space: gfx::Rect(194, 200, 12, 8)
1104 // - new location in target space: gfx::Rect(189, 205, 12, 8)
1105 EXPECT_EQ(gfx::Rect(6, 8).ToString(), grand_child_damage_rect
.ToString());
1106 EXPECT_EQ(gfx::Rect(189, 200, 17, 13).ToString(),
1107 child_damage_rect
.ToString());
1108 EXPECT_EQ(gfx::Rect(289, 300, 17, 13).ToString(),
1109 root_damage_rect
.ToString());
1111 // CASE 3: removing the reflection should cause the entire region including
1112 // reflection to damage the target surface.
1113 ClearDamageForAllSurfaces(root
.get());
1114 grand_child1
->SetReplicaLayer(nullptr);
1115 grand_child1
->SetHasRenderSurface(false);
1116 EmulateDrawingOneFrame(root
.get());
1117 ASSERT_EQ(old_content_rect
.width(),
1118 child1
->render_surface()->content_rect().width());
1119 ASSERT_EQ(old_content_rect
.height(),
1120 child1
->render_surface()->content_rect().height());
1122 EXPECT_FALSE(grand_child1
->render_surface());
1124 child1
->render_surface()->damage_tracker()->current_damage_rect();
1126 root
->render_surface()->damage_tracker()->current_damage_rect();
1128 EXPECT_EQ(gfx::Rect(189, 205, 12, 8).ToString(),
1129 child_damage_rect
.ToString());
1130 EXPECT_EQ(gfx::Rect(289, 305, 12, 8).ToString(), root_damage_rect
.ToString());
1133 TEST_F(DamageTrackerTest
, VerifyDamageForMask
) {
1134 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
1135 LayerImpl
* child
= root
->children()[0];
1137 // In the current implementation of the damage tracker, changes to mask
1138 // layers should damage the entire corresponding surface.
1140 ClearDamageForAllSurfaces(root
.get());
1142 // Set up the mask layer.
1144 scoped_ptr
<LayerImpl
> mask_layer
=
1145 LayerImpl::Create(host_impl_
.active_tree(), 3);
1146 mask_layer
->SetPosition(child
->position());
1147 mask_layer
->SetBounds(child
->bounds());
1148 child
->SetMaskLayer(mask_layer
.Pass());
1149 child
->SetHasRenderSurface(true);
1151 LayerImpl
* mask_layer
= child
->mask_layer();
1153 // Add opacity and a grand_child so that the render surface persists even
1154 // after we remove the mask.
1156 scoped_ptr
<LayerImpl
> grand_child
=
1157 LayerImpl::Create(host_impl_
.active_tree(), 4);
1158 grand_child
->SetPosition(gfx::PointF(2.f
, 2.f
));
1159 grand_child
->SetBounds(gfx::Size(2, 2));
1160 grand_child
->SetDrawsContent(true);
1161 child
->AddChild(grand_child
.Pass());
1163 EmulateDrawingOneFrame(root
.get());
1165 // CASE 1: the update_rect on a mask layer should damage the entire target
1167 ClearDamageForAllSurfaces(root
.get());
1168 mask_layer
->SetUpdateRect(gfx::Rect(1, 2, 3, 4));
1169 EmulateDrawingOneFrame(root
.get());
1170 gfx::Rect child_damage_rect
=
1171 child
->render_surface()->damage_tracker()->current_damage_rect();
1172 EXPECT_EQ(gfx::Rect(30, 30).ToString(), child_damage_rect
.ToString());
1174 // CASE 2: a property change on the mask layer should damage the entire
1177 // Advance one frame without damage so that we know the damage rect is not
1178 // leftover from the previous case.
1179 ClearDamageForAllSurfaces(root
.get());
1180 EmulateDrawingOneFrame(root
.get());
1182 child
->render_surface()->damage_tracker()->current_damage_rect();
1183 EXPECT_TRUE(child_damage_rect
.IsEmpty());
1185 // Then test the property change.
1186 ClearDamageForAllSurfaces(root
.get());
1187 mask_layer
->SetStackingOrderChanged(true);
1189 EmulateDrawingOneFrame(root
.get());
1191 child
->render_surface()->damage_tracker()->current_damage_rect();
1192 EXPECT_EQ(gfx::Rect(30, 30).ToString(), child_damage_rect
.ToString());
1194 // CASE 3: removing the mask also damages the entire target surface.
1197 // Advance one frame without damage so that we know the damage rect is not
1198 // leftover from the previous case.
1199 ClearDamageForAllSurfaces(root
.get());
1200 EmulateDrawingOneFrame(root
.get());
1202 child
->render_surface()->damage_tracker()->current_damage_rect();
1203 EXPECT_TRUE(child_damage_rect
.IsEmpty());
1205 // Then test mask removal.
1206 ClearDamageForAllSurfaces(root
.get());
1207 child
->SetMaskLayer(nullptr);
1208 ASSERT_TRUE(child
->LayerPropertyChanged());
1209 EmulateDrawingOneFrame(root
.get());
1211 // Sanity check that a render surface still exists.
1212 ASSERT_TRUE(child
->render_surface());
1215 child
->render_surface()->damage_tracker()->current_damage_rect();
1216 EXPECT_EQ(gfx::Rect(30, 30).ToString(), child_damage_rect
.ToString());
1219 TEST_F(DamageTrackerTest
, VerifyDamageForReplicaMask
) {
1220 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithTwoSurfaces();
1221 LayerImpl
* child1
= root
->children()[0];
1222 LayerImpl
* grand_child1
= child1
->children()[0];
1224 // Changes to a replica's mask should not damage the original surface,
1225 // because it is not masked. But it does damage the ancestor target surface.
1227 ClearDamageForAllSurfaces(root
.get());
1229 // Create a reflection about the left edge of grand_child1.
1231 scoped_ptr
<LayerImpl
> grand_child1_replica
=
1232 LayerImpl::Create(host_impl_
.active_tree(), 6);
1233 grand_child1_replica
->SetPosition(gfx::PointF());
1234 gfx::Transform reflection
;
1235 reflection
.Scale3d(-1.0, 1.0, 1.0);
1236 grand_child1_replica
->SetTransform(reflection
);
1237 grand_child1
->SetReplicaLayer(grand_child1_replica
.Pass());
1238 grand_child1
->SetHasRenderSurface(true);
1240 LayerImpl
* grand_child1_replica
= grand_child1
->replica_layer();
1242 // Set up the mask layer on the replica layer
1244 scoped_ptr
<LayerImpl
> replica_mask_layer
=
1245 LayerImpl::Create(host_impl_
.active_tree(), 7);
1246 replica_mask_layer
->SetPosition(gfx::PointF());
1247 replica_mask_layer
->SetBounds(grand_child1
->bounds());
1248 grand_child1_replica
->SetMaskLayer(replica_mask_layer
.Pass());
1250 LayerImpl
* replica_mask_layer
= grand_child1_replica
->mask_layer();
1252 EmulateDrawingOneFrame(root
.get());
1254 // Sanity check that the appropriate render surfaces were created
1255 ASSERT_TRUE(grand_child1
->render_surface());
1257 // CASE 1: a property change on the mask should damage only the reflected
1258 // region on the target surface.
1259 ClearDamageForAllSurfaces(root
.get());
1260 replica_mask_layer
->SetStackingOrderChanged(true);
1261 EmulateDrawingOneFrame(root
.get());
1263 gfx::Rect grand_child_damage_rect
=
1264 grand_child1
->render_surface()->damage_tracker()->current_damage_rect();
1265 gfx::Rect child_damage_rect
=
1266 child1
->render_surface()->damage_tracker()->current_damage_rect();
1268 EXPECT_TRUE(grand_child_damage_rect
.IsEmpty());
1269 EXPECT_EQ(gfx::Rect(194, 200, 6, 8).ToString(), child_damage_rect
.ToString());
1271 // CASE 2: removing the replica mask damages only the reflected region on the
1274 ClearDamageForAllSurfaces(root
.get());
1275 grand_child1_replica
->SetMaskLayer(nullptr);
1276 EmulateDrawingOneFrame(root
.get());
1278 grand_child_damage_rect
=
1279 grand_child1
->render_surface()->damage_tracker()->
1280 current_damage_rect();
1282 child1
->render_surface()->damage_tracker()->current_damage_rect();
1284 EXPECT_TRUE(grand_child_damage_rect
.IsEmpty());
1285 EXPECT_EQ(gfx::Rect(194, 200, 6, 8).ToString(), child_damage_rect
.ToString());
1288 TEST_F(DamageTrackerTest
, VerifyDamageForReplicaMaskWithTransformOrigin
) {
1289 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithTwoSurfaces();
1290 LayerImpl
* child1
= root
->children()[0];
1291 LayerImpl
* grand_child1
= child1
->children()[0];
1293 // Verify that the correct replica_origin_transform is used for the
1295 ClearDamageForAllSurfaces(root
.get());
1297 // This is not actually the transform origin point being tested, but by
1299 // expected to be the same as the replica's anchor point.
1300 grand_child1
->SetTransformOrigin(
1301 gfx::Point3F(grand_child1
->bounds().width(), 0.f
, 0.f
));
1304 scoped_ptr
<LayerImpl
> grand_child1_replica
=
1305 LayerImpl::Create(host_impl_
.active_tree(), 6);
1306 grand_child1_replica
->SetPosition(gfx::PointF());
1308 // This is the anchor being tested.
1309 grand_child1_replica
->SetTransformOrigin(
1310 gfx::Point3F(grand_child1
->bounds().width(), 0.f
, 0.f
));
1311 gfx::Transform reflection
;
1312 reflection
.Scale3d(-1.0, 1.0, 1.0);
1313 grand_child1_replica
->SetTransform(reflection
);
1314 grand_child1
->SetReplicaLayer(grand_child1_replica
.Pass());
1315 grand_child1
->SetHasRenderSurface(true);
1317 LayerImpl
* grand_child1_replica
= grand_child1
->replica_layer();
1319 // Set up the mask layer on the replica layer
1321 scoped_ptr
<LayerImpl
> replica_mask_layer
=
1322 LayerImpl::Create(host_impl_
.active_tree(), 7);
1323 replica_mask_layer
->SetPosition(gfx::PointF());
1324 // Note: this is not the transform origin being tested.
1325 replica_mask_layer
->SetBounds(grand_child1
->bounds());
1326 grand_child1_replica
->SetMaskLayer(replica_mask_layer
.Pass());
1328 LayerImpl
* replica_mask_layer
= grand_child1_replica
->mask_layer();
1330 EmulateDrawingOneFrame(root
.get());
1332 // Sanity check that the appropriate render surfaces were created
1333 ASSERT_TRUE(grand_child1
->render_surface());
1335 // A property change on the replica_mask should damage the reflected region on
1336 // the target surface.
1337 ClearDamageForAllSurfaces(root
.get());
1338 replica_mask_layer
->SetStackingOrderChanged(true);
1340 EmulateDrawingOneFrame(root
.get());
1342 gfx::Rect child_damage_rect
=
1343 child1
->render_surface()->damage_tracker()->current_damage_rect();
1344 EXPECT_EQ(gfx::Rect(206, 200, 6, 8).ToString(), child_damage_rect
.ToString());
1347 TEST_F(DamageTrackerTest
, DamageWhenAddedExternally
) {
1348 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
1349 LayerImpl
* child
= root
->children()[0];
1351 // Case 1: This test ensures that when the tracker is given damage, that
1352 // it is included with any other partial damage.
1354 ClearDamageForAllSurfaces(root
.get());
1355 child
->SetUpdateRect(gfx::Rect(10, 11, 12, 13));
1356 root
->render_surface()->damage_tracker()->AddDamageNextUpdate(
1357 gfx::Rect(15, 16, 32, 33));
1358 EmulateDrawingOneFrame(root
.get());
1359 gfx::Rect root_damage_rect
=
1360 root
->render_surface()->damage_tracker()->current_damage_rect();
1361 EXPECT_EQ(gfx::UnionRects(gfx::Rect(15, 16, 32, 33),
1362 gfx::Rect(100 + 10, 100 + 11, 12, 13)).ToString(),
1363 root_damage_rect
.ToString());
1365 // Case 2: An additional sanity check that adding damage works even when
1366 // nothing on the layer tree changed.
1368 ClearDamageForAllSurfaces(root
.get());
1369 root
->render_surface()->damage_tracker()->AddDamageNextUpdate(
1370 gfx::Rect(30, 31, 14, 15));
1371 EmulateDrawingOneFrame(root
.get());
1373 root
->render_surface()->damage_tracker()->current_damage_rect();
1374 EXPECT_EQ(gfx::Rect(30, 31, 14, 15).ToString(), root_damage_rect
.ToString());
1377 TEST_F(DamageTrackerTest
, VerifyDamageForEmptyLayerList
) {
1378 // Though it should never happen, its a good idea to verify that the damage
1379 // tracker does not crash when it receives an empty layer_list.
1381 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
.active_tree(), 1);
1382 root
->SetHasRenderSurface(true);
1383 root
->draw_properties().render_target
= root
.get();
1385 ASSERT_TRUE(root
== root
->render_target());
1386 RenderSurfaceImpl
* target_surface
= root
->render_surface();
1388 LayerImplList empty_list
;
1389 target_surface
->damage_tracker()->UpdateDamageTrackingState(
1391 target_surface
->OwningLayerId(),
1395 FilterOperations());
1397 gfx::Rect damage_rect
=
1398 target_surface
->damage_tracker()->current_damage_rect();
1399 EXPECT_TRUE(damage_rect
.IsEmpty());
1402 TEST_F(DamageTrackerTest
, VerifyDamageAccumulatesUntilReset
) {
1403 // If damage is not cleared, it should accumulate.
1405 scoped_ptr
<LayerImpl
> root
= CreateAndSetUpTestTreeWithOneSurface();
1406 LayerImpl
* child
= root
->children()[0];
1408 ClearDamageForAllSurfaces(root
.get());
1409 child
->SetUpdateRect(gfx::Rect(10.f
, 11.f
, 1.f
, 2.f
));
1410 EmulateDrawingOneFrame(root
.get());
1412 // Sanity check damage after the first frame; this isnt the actual test yet.
1413 gfx::Rect root_damage_rect
=
1414 root
->render_surface()->damage_tracker()->current_damage_rect();
1415 EXPECT_EQ(gfx::Rect(110, 111, 1, 2).ToString(), root_damage_rect
.ToString());
1417 // New damage, without having cleared the previous damage, should be unioned
1418 // to the previous one.
1419 child
->SetUpdateRect(gfx::Rect(20, 25, 1, 2));
1420 EmulateDrawingOneFrame(root
.get());
1422 root
->render_surface()->damage_tracker()->current_damage_rect();
1423 EXPECT_EQ(gfx::Rect(110, 111, 11, 16).ToString(),
1424 root_damage_rect
.ToString());
1426 // If we notify the damage tracker that we drew the damaged area, then damage
1427 // should be emptied.
1428 root
->render_surface()->damage_tracker()->DidDrawDamagedArea();
1430 root
->render_surface()->damage_tracker()->current_damage_rect();
1431 EXPECT_TRUE(root_damage_rect
.IsEmpty());
1433 // Damage should remain empty even after one frame, since there's yet no new
1435 EmulateDrawingOneFrame(root
.get());
1437 root
->render_surface()->damage_tracker()->current_damage_rect();
1438 EXPECT_TRUE(root_damage_rect
.IsEmpty());
1441 TEST_F(DamageTrackerTest
, HugeDamageRect
) {
1442 // This number is so large that we start losting floating point accuracy.
1443 const int kBigNumber
= 900000000;
1444 // Walk over a range to find floating point inaccuracy boundaries that move
1445 // toward the wrong direction.
1446 const int kRange
= 5000;
1448 for (int i
= 0; i
< kRange
; ++i
) {
1449 scoped_ptr
<LayerImpl
> root
= CreateTestTreeWithOneSurface();
1450 LayerImpl
* child
= root
->children()[0];
1452 gfx::Transform transform
;
1453 transform
.Translate(-kBigNumber
, -kBigNumber
);
1455 // The child layer covers (0, 0, i, i) of the viewport,
1456 // but has a huge negative position.
1457 child
->SetPosition(gfx::PointF());
1458 child
->SetBounds(gfx::Size(kBigNumber
+ i
, kBigNumber
+ i
));
1459 child
->SetTransform(transform
);
1460 EmulateDrawingOneFrame(root
.get());
1462 // The expected damage should cover the visible part of the child layer,
1463 // which is (0, 0, i, i) in the viewport.
1464 gfx::Rect root_damage_rect
=
1465 root
->render_surface()->damage_tracker()->current_damage_rect();
1466 gfx::Rect damage_we_care_about
= gfx::Rect(i
, i
);
1467 EXPECT_LE(damage_we_care_about
.right(), root_damage_rect
.right());
1468 EXPECT_LE(damage_we_care_about
.bottom(), root_damage_rect
.bottom());