Add ICU message format support
[chromium-blink-merge.git] / cc / trees / damage_tracker_unittest.cc
blob831b1f718ec22be4642adca1454af07326c232a2
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"
24 namespace cc {
25 namespace {
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
56 // and surfaces.
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 {
80 public:
81 DamageTrackerTest()
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());
101 return root.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());
151 return root.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());
161 return root.Pass();
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());
171 return root.Pass();
174 protected:
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
227 // the surface.
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
240 // damage.
241 ClearDamageForAllSurfaces(root.get());
242 child->SetUpdateRect(gfx::Rect(10, 11, 12, 13));
243 EmulateDrawingOneFrame(root.get());
244 root_damage_rect =
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).
257 root_damage_rect =
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
267 // to the surface.
268 ClearDamageForAllSurfaces(root.get());
269 child->AddDamageRect(gfx::RectF(10.f, 11.f, 12.f, 13.f));
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
279 // damage.
280 ClearDamageForAllSurfaces(root.get());
281 child->AddDamageRect(gfx::RectF(10.f, 11.f, 12.f, 13.f));
282 EmulateDrawingOneFrame(root.get());
283 root_damage_rect =
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::RectF(20.f, 25.f, 1.f, 2.f));
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).
295 root_damage_rect =
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::RectF(20.f, 25.f, 1.f, 2.f));
303 child->AddDamageRect(gfx::RectF(10.f, 15.f, 3.f, 4.f));
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).
308 root_damage_rect =
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::RectF(5.f, 6.f, 12.f, 13.f));
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::RectF(10.f, 11.f, 12.f, 13.f));
336 child->SetUpdateRect(gfx::Rect(10, 11, 14, 15));
337 EmulateDrawingOneFrame(root.get());
338 root_damage_rect =
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::RectF(20.f, 25.f, 2.f, 3.f));
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).
351 root_damage_rect =
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());
386 root_damage_rect =
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));
397 root_damage_rect =
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
433 // region.
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));
438 root_damage_rect =
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);
465 // Set up the child
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,
520 -outset_top,
521 -outset_right,
522 -outset_bottom);
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));
539 // Setting the filter will damage the whole surface.
540 ClearDamageForAllSurfaces(root.get());
541 child->SetHasRenderSurface(true);
542 child->SetFilters(filters);
543 EmulateDrawingOneFrame(root.get());
544 root_damage_rect =
545 root->render_surface()->damage_tracker()->current_damage_rect();
546 child_damage_rect =
547 child->render_surface()->damage_tracker()->current_damage_rect();
548 EXPECT_EQ(gfx::Rect(100, 100, 30, 30).ToString(),
549 root_damage_rect.ToString());
550 EXPECT_EQ(gfx::Rect(30, 30).ToString(), child_damage_rect.ToString());
552 // CASE 1: Setting the update rect should damage the whole surface (for now)
553 ClearDamageForAllSurfaces(root.get());
554 child->SetUpdateRect(gfx::Rect(1, 1));
555 EmulateDrawingOneFrame(root.get());
557 root_damage_rect =
558 root->render_surface()->damage_tracker()->current_damage_rect();
559 child_damage_rect =
560 child->render_surface()->damage_tracker()->current_damage_rect();
561 EXPECT_EQ(gfx::Rect(100, 100, 30, 30).ToString(),
562 root_damage_rect.ToString());
563 EXPECT_EQ(gfx::Rect(30.f, 30.f).ToString(), child_damage_rect.ToString());
566 TEST_F(DamageTrackerTest, VerifyDamageForBackgroundBlurredChild) {
567 scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithTwoSurfaces();
568 LayerImpl* child1 = root->children()[0];
569 LayerImpl* child2 = root->children()[1];
571 // Allow us to set damage on child1 too.
572 child1->SetDrawsContent(true);
574 FilterOperations filters;
575 filters.Append(FilterOperation::CreateBlurFilter(2.f));
576 int outset_top, outset_right, outset_bottom, outset_left;
577 filters.GetOutsets(&outset_top, &outset_right, &outset_bottom, &outset_left);
579 // Setting the filter will damage the whole surface.
580 ClearDamageForAllSurfaces(root.get());
581 child1->SetBackgroundFilters(filters);
582 EmulateDrawingOneFrame(root.get());
584 // CASE 1: Setting the update rect should cause the corresponding damage to
585 // the surface, blurred based on the size of the child's background
586 // blur filter.
587 ClearDamageForAllSurfaces(root.get());
588 root->SetUpdateRect(gfx::Rect(297, 297, 2, 2));
589 EmulateDrawingOneFrame(root.get());
591 gfx::Rect root_damage_rect =
592 root->render_surface()->damage_tracker()->current_damage_rect();
593 // Damage position on the surface should be a composition of the damage on
594 // the root and on child2. Damage on the root should be: position of
595 // update_rect (297, 297), but expanded by the blur outsets.
596 gfx::Rect expected_damage_rect = gfx::Rect(297, 297, 2, 2);
598 expected_damage_rect.Inset(-outset_left,
599 -outset_top,
600 -outset_right,
601 -outset_bottom);
602 EXPECT_EQ(expected_damage_rect.ToString(), root_damage_rect.ToString());
604 // CASE 2: Setting the update rect should cause the corresponding damage to
605 // the surface, blurred based on the size of the child's background
606 // blur filter. Since the damage extends to the right/bottom outside
607 // of the blurred layer, only the left/top should end up expanded.
608 ClearDamageForAllSurfaces(root.get());
609 root->SetUpdateRect(gfx::Rect(297, 297, 30, 30));
610 EmulateDrawingOneFrame(root.get());
612 root_damage_rect =
613 root->render_surface()->damage_tracker()->current_damage_rect();
614 // Damage position on the surface should be a composition of the damage on
615 // the root and on child2. Damage on the root should be: position of
616 // update_rect (297, 297), but expanded on the left/top by the blur outsets.
617 expected_damage_rect = gfx::Rect(297, 297, 30, 30);
619 expected_damage_rect.Inset(-outset_left,
620 -outset_top,
623 EXPECT_EQ(expected_damage_rect.ToString(), root_damage_rect.ToString());
625 // CASE 3: Setting this update rect outside the blurred content_bounds of the
626 // blurred child1 will not cause it to be expanded.
627 ClearDamageForAllSurfaces(root.get());
628 root->SetUpdateRect(gfx::Rect(30, 30, 2, 2));
629 EmulateDrawingOneFrame(root.get());
631 root_damage_rect =
632 root->render_surface()->damage_tracker()->current_damage_rect();
633 // Damage on the root should be: position of update_rect (30, 30), not
634 // expanded.
635 expected_damage_rect = gfx::Rect(30, 30, 2, 2);
637 EXPECT_EQ(expected_damage_rect.ToString(), root_damage_rect.ToString());
639 // CASE 4: Setting this update rect inside the blurred content_bounds but
640 // outside the original content_bounds of the blurred child1 will
641 // cause it to be expanded.
642 ClearDamageForAllSurfaces(root.get());
643 root->SetUpdateRect(gfx::Rect(99, 99, 1, 1));
644 EmulateDrawingOneFrame(root.get());
646 root_damage_rect =
647 root->render_surface()->damage_tracker()->current_damage_rect();
648 // Damage on the root should be: position of update_rect (99, 99), expanded by
649 // the blurring on child1, but since it is 1 pixel outside the layer, the
650 // expanding should be reduced by 1.
651 expected_damage_rect = gfx::Rect(99, 99, 1, 1);
653 expected_damage_rect.Inset(-outset_left + 1,
654 -outset_top + 1,
655 -outset_right,
656 -outset_bottom);
657 EXPECT_EQ(expected_damage_rect.ToString(), root_damage_rect.ToString());
659 // CASE 5: Setting the update rect on child2, which is above child1, will
660 // not get blurred by child1, so it does not need to get expanded.
661 ClearDamageForAllSurfaces(root.get());
662 child2->SetUpdateRect(gfx::Rect(1, 1));
663 EmulateDrawingOneFrame(root.get());
665 root_damage_rect =
666 root->render_surface()->damage_tracker()->current_damage_rect();
667 // Damage on child2 should be: position of update_rect offset by the child's
668 // position (11, 11), and not expanded by anything.
669 expected_damage_rect = gfx::Rect(11, 11, 1, 1);
671 EXPECT_EQ(expected_damage_rect.ToString(), root_damage_rect.ToString());
673 // CASE 6: Setting the update rect on child1 will also blur the damage, so
674 // that any pixels needed for the blur are redrawn in the current
675 // frame.
676 ClearDamageForAllSurfaces(root.get());
677 child1->SetUpdateRect(gfx::Rect(1, 1));
678 EmulateDrawingOneFrame(root.get());
680 root_damage_rect =
681 root->render_surface()->damage_tracker()->current_damage_rect();
682 // Damage on child1 should be: position of update_rect offset by the child's
683 // position (100, 100), and expanded by the damage.
684 expected_damage_rect = gfx::Rect(100, 100, 1, 1);
686 expected_damage_rect.Inset(-outset_left,
687 -outset_top,
688 -outset_right,
689 -outset_bottom);
690 EXPECT_EQ(expected_damage_rect.ToString(), root_damage_rect.ToString());
693 TEST_F(DamageTrackerTest, VerifyDamageForAddingAndRemovingLayer) {
694 scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithOneSurface();
695 LayerImpl* child1 = root->children()[0];
697 // CASE 1: Adding a new layer should cause the appropriate damage.
699 ClearDamageForAllSurfaces(root.get());
701 scoped_ptr<LayerImpl> child2 =
702 LayerImpl::Create(host_impl_.active_tree(), 3);
703 child2->SetPosition(gfx::PointF(400.f, 380.f));
704 child2->SetBounds(gfx::Size(6, 8));
705 child2->SetDrawsContent(true);
706 root->AddChild(child2.Pass());
708 EmulateDrawingOneFrame(root.get());
710 // Sanity check - all 3 layers should be on the same render surface; render
711 // surfaces are tested elsewhere.
712 ASSERT_EQ(3u, root->render_surface()->layer_list().size());
714 gfx::Rect root_damage_rect =
715 root->render_surface()->damage_tracker()->current_damage_rect();
716 EXPECT_EQ(gfx::Rect(400, 380, 6, 8).ToString(), root_damage_rect.ToString());
718 // CASE 2: If the layer is removed, its entire old layer becomes exposed, not
719 // just the last update rect.
721 // Advance one frame without damage so that we know the damage rect is not
722 // leftover from the previous case.
723 ClearDamageForAllSurfaces(root.get());
724 EmulateDrawingOneFrame(root.get());
726 root_damage_rect =
727 root->render_surface()->damage_tracker()->current_damage_rect();
728 EXPECT_TRUE(root_damage_rect.IsEmpty());
730 // Then, test removing child1.
731 root->RemoveChild(child1);
732 child1 = NULL;
733 EmulateDrawingOneFrame(root.get());
735 root_damage_rect =
736 root->render_surface()->damage_tracker()->current_damage_rect();
737 EXPECT_EQ(gfx::Rect(100, 100, 30, 30).ToString(),
738 root_damage_rect.ToString());
741 TEST_F(DamageTrackerTest, VerifyDamageForNewUnchangedLayer) {
742 // If child2 is added to the layer tree, but it doesn't have any explicit
743 // damage of its own, it should still indeed damage the target surface.
745 scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithOneSurface();
747 ClearDamageForAllSurfaces(root.get());
749 scoped_ptr<LayerImpl> child2 =
750 LayerImpl::Create(host_impl_.active_tree(), 3);
751 child2->SetPosition(gfx::PointF(400.f, 380.f));
752 child2->SetBounds(gfx::Size(6, 8));
753 child2->SetDrawsContent(true);
754 child2->ResetAllChangeTrackingForSubtree();
755 // Sanity check the initial conditions of the test, if these asserts
756 // trigger, it means the test no longer actually covers the intended
757 // scenario.
758 ASSERT_FALSE(child2->LayerPropertyChanged());
759 ASSERT_TRUE(child2->update_rect().IsEmpty());
760 root->AddChild(child2.Pass());
762 EmulateDrawingOneFrame(root.get());
764 // Sanity check - all 3 layers should be on the same render surface; render
765 // surfaces are tested elsewhere.
766 ASSERT_EQ(3u, root->render_surface()->layer_list().size());
768 gfx::Rect root_damage_rect =
769 root->render_surface()->damage_tracker()->current_damage_rect();
770 EXPECT_EQ(gfx::Rect(400, 380, 6, 8).ToString(), root_damage_rect.ToString());
773 TEST_F(DamageTrackerTest, VerifyDamageForMultipleLayers) {
774 scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithOneSurface();
775 LayerImpl* child1 = root->children()[0];
777 // In this test we don't want the above tree manipulation to be considered
778 // part of the same frame.
779 ClearDamageForAllSurfaces(root.get());
781 scoped_ptr<LayerImpl> child2 =
782 LayerImpl::Create(host_impl_.active_tree(), 3);
783 child2->SetPosition(gfx::PointF(400.f, 380.f));
784 child2->SetBounds(gfx::Size(6, 8));
785 child2->SetDrawsContent(true);
786 root->AddChild(child2.Pass());
788 LayerImpl* child2 = root->children()[1];
789 EmulateDrawingOneFrame(root.get());
791 // Damaging two layers simultaneously should cause combined damage.
792 // - child1 update rect in surface space: gfx::Rect(100, 100, 1, 2);
793 // - child2 update rect in surface space: gfx::Rect(400, 380, 3, 4);
794 ClearDamageForAllSurfaces(root.get());
795 child1->SetUpdateRect(gfx::Rect(1, 2));
796 child2->SetUpdateRect(gfx::Rect(3, 4));
797 EmulateDrawingOneFrame(root.get());
798 gfx::Rect root_damage_rect =
799 root->render_surface()->damage_tracker()->current_damage_rect();
800 EXPECT_EQ(gfx::Rect(100, 100, 303, 284).ToString(),
801 root_damage_rect.ToString());
804 TEST_F(DamageTrackerTest, VerifyDamageForNestedSurfaces) {
805 scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithTwoSurfaces();
806 LayerImpl* child1 = root->children()[0];
807 LayerImpl* child2 = root->children()[1];
808 LayerImpl* grand_child1 = root->children()[0]->children()[0];
809 gfx::Rect child_damage_rect;
810 gfx::Rect root_damage_rect;
812 // CASE 1: Damage to a descendant surface should propagate properly to
813 // ancestor surface.
814 ClearDamageForAllSurfaces(root.get());
815 grand_child1->SetOpacity(0.5f);
816 EmulateDrawingOneFrame(root.get());
817 child_damage_rect =
818 child1->render_surface()->damage_tracker()->current_damage_rect();
819 root_damage_rect =
820 root->render_surface()->damage_tracker()->current_damage_rect();
821 EXPECT_EQ(gfx::Rect(200, 200, 6, 8).ToString(), child_damage_rect.ToString());
822 EXPECT_EQ(gfx::Rect(300, 300, 6, 8).ToString(), root_damage_rect.ToString());
824 // CASE 2: Same as previous case, but with additional damage elsewhere that
825 // should be properly unioned.
826 // - child1 surface damage in root surface space:
827 // gfx::Rect(300, 300, 6, 8);
828 // - child2 damage in root surface space:
829 // gfx::Rect(11, 11, 18, 18);
830 ClearDamageForAllSurfaces(root.get());
831 grand_child1->SetOpacity(0.7f);
832 child2->SetOpacity(0.7f);
833 EmulateDrawingOneFrame(root.get());
834 child_damage_rect =
835 child1->render_surface()->damage_tracker()->current_damage_rect();
836 root_damage_rect =
837 root->render_surface()->damage_tracker()->current_damage_rect();
838 EXPECT_EQ(gfx::Rect(200, 200, 6, 8).ToString(), child_damage_rect.ToString());
839 EXPECT_EQ(gfx::Rect(11, 11, 295, 297).ToString(),
840 root_damage_rect.ToString());
843 TEST_F(DamageTrackerTest, VerifyDamageForSurfaceChangeFromDescendantLayer) {
844 // If descendant layer changes and affects the content bounds of the render
845 // surface, then the entire descendant surface should be damaged, and it
846 // should damage its ancestor surface with the old and new surface regions.
848 // This is a tricky case, since only the first grand_child changes, but the
849 // entire surface should be marked dirty.
851 scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithTwoSurfaces();
852 LayerImpl* child1 = root->children()[0];
853 LayerImpl* grand_child1 = root->children()[0]->children()[0];
854 gfx::Rect child_damage_rect;
855 gfx::Rect root_damage_rect;
857 ClearDamageForAllSurfaces(root.get());
858 grand_child1->SetPosition(gfx::PointF(195.f, 205.f));
859 EmulateDrawingOneFrame(root.get());
860 child_damage_rect =
861 child1->render_surface()->damage_tracker()->current_damage_rect();
862 root_damage_rect =
863 root->render_surface()->damage_tracker()->current_damage_rect();
865 // The new surface bounds should be damaged entirely, even though only one of
866 // the layers changed.
867 EXPECT_EQ(gfx::Rect(190, 190, 11, 23).ToString(),
868 child_damage_rect.ToString());
870 // Damage to the root surface should be the union of child1's *entire* render
871 // surface (in target space), and its old exposed area (also in target
872 // space).
873 EXPECT_EQ(gfx::Rect(290, 290, 16, 23).ToString(),
874 root_damage_rect.ToString());
877 TEST_F(DamageTrackerTest, VerifyDamageForSurfaceChangeFromAncestorLayer) {
878 // An ancestor/owning layer changes that affects the position/transform of
879 // the render surface. Note that in this case, the layer_property_changed flag
880 // already propagates to the subtree (tested in LayerImpltest), which damages
881 // the entire child1 surface, but the damage tracker still needs the correct
882 // logic to compute the exposed region on the root surface.
884 // TODO(shawnsingh): the expectations of this test case should change when we
885 // add support for a unique scissor_rect per RenderSurface. In that case, the
886 // child1 surface should be completely unchanged, since we are only
887 // transforming it, while the root surface would be damaged appropriately.
889 scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithTwoSurfaces();
890 LayerImpl* child1 = root->children()[0];
891 gfx::Rect child_damage_rect;
892 gfx::Rect root_damage_rect;
894 ClearDamageForAllSurfaces(root.get());
895 child1->SetPosition(gfx::PointF(50.f, 50.f));
896 EmulateDrawingOneFrame(root.get());
897 child_damage_rect =
898 child1->render_surface()->damage_tracker()->current_damage_rect();
899 root_damage_rect =
900 root->render_surface()->damage_tracker()->current_damage_rect();
902 // The new surface bounds should be damaged entirely.
903 EXPECT_EQ(gfx::Rect(190, 190, 16, 18).ToString(),
904 child_damage_rect.ToString());
906 // The entire child1 surface and the old exposed child1 surface should damage
907 // the root surface.
908 // - old child1 surface in target space: gfx::Rect(290, 290, 16, 18)
909 // - new child1 surface in target space: gfx::Rect(240, 240, 16, 18)
910 EXPECT_EQ(gfx::Rect(240, 240, 66, 68).ToString(),
911 root_damage_rect.ToString());
914 TEST_F(DamageTrackerTest, VerifyDamageForAddingAndRemovingRenderSurfaces) {
915 scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithTwoSurfaces();
916 LayerImpl* child1 = root->children()[0];
917 gfx::Rect child_damage_rect;
918 gfx::Rect root_damage_rect;
920 // CASE 1: If a descendant surface disappears, its entire old area becomes
921 // exposed.
922 ClearDamageForAllSurfaces(root.get());
923 child1->SetHasRenderSurface(false);
924 EmulateDrawingOneFrame(root.get());
926 // Sanity check that there is only one surface now.
927 ASSERT_FALSE(child1->render_surface());
928 ASSERT_EQ(4u, root->render_surface()->layer_list().size());
930 root_damage_rect =
931 root->render_surface()->damage_tracker()->current_damage_rect();
932 EXPECT_EQ(gfx::Rect(290, 290, 16, 18).ToString(),
933 root_damage_rect.ToString());
935 // CASE 2: If a descendant surface appears, its entire old area becomes
936 // exposed.
938 // Cycle one frame of no change, just to sanity check that the next rect is
939 // not because of the old damage state.
940 ClearDamageForAllSurfaces(root.get());
941 EmulateDrawingOneFrame(root.get());
942 root_damage_rect =
943 root->render_surface()->damage_tracker()->current_damage_rect();
944 EXPECT_TRUE(root_damage_rect.IsEmpty());
946 // Then change the tree so that the render surface is added back.
947 ClearDamageForAllSurfaces(root.get());
948 child1->SetHasRenderSurface(true);
950 EmulateDrawingOneFrame(root.get());
952 // Sanity check that there is a new surface now.
953 ASSERT_TRUE(child1->render_surface());
954 EXPECT_EQ(3u, root->render_surface()->layer_list().size());
955 EXPECT_EQ(2u, child1->render_surface()->layer_list().size());
957 child_damage_rect =
958 child1->render_surface()->damage_tracker()->current_damage_rect();
959 root_damage_rect =
960 root->render_surface()->damage_tracker()->current_damage_rect();
961 EXPECT_EQ(gfx::Rect(190, 190, 16, 18).ToString(),
962 child_damage_rect.ToString());
963 EXPECT_EQ(gfx::Rect(290, 290, 16, 18).ToString(),
964 root_damage_rect.ToString());
967 TEST_F(DamageTrackerTest, VerifyNoDamageWhenNothingChanged) {
968 scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithTwoSurfaces();
969 LayerImpl* child1 = root->children()[0];
970 gfx::Rect child_damage_rect;
971 gfx::Rect root_damage_rect;
973 // CASE 1: If nothing changes, the damage rect should be empty.
975 ClearDamageForAllSurfaces(root.get());
976 EmulateDrawingOneFrame(root.get());
977 child_damage_rect =
978 child1->render_surface()->damage_tracker()->current_damage_rect();
979 root_damage_rect =
980 root->render_surface()->damage_tracker()->current_damage_rect();
981 EXPECT_TRUE(child_damage_rect.IsEmpty());
982 EXPECT_TRUE(root_damage_rect.IsEmpty());
984 // CASE 2: If nothing changes twice in a row, the damage rect should still be
985 // empty.
987 ClearDamageForAllSurfaces(root.get());
988 EmulateDrawingOneFrame(root.get());
989 child_damage_rect =
990 child1->render_surface()->damage_tracker()->current_damage_rect();
991 root_damage_rect =
992 root->render_surface()->damage_tracker()->current_damage_rect();
993 EXPECT_TRUE(child_damage_rect.IsEmpty());
994 EXPECT_TRUE(root_damage_rect.IsEmpty());
997 TEST_F(DamageTrackerTest, VerifyNoDamageForUpdateRectThatDoesNotDrawContent) {
998 scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithTwoSurfaces();
999 LayerImpl* child1 = root->children()[0];
1000 gfx::Rect child_damage_rect;
1001 gfx::Rect root_damage_rect;
1003 // In our specific tree, the update rect of child1 should not cause any
1004 // damage to any surface because it does not actually draw content.
1005 ClearDamageForAllSurfaces(root.get());
1006 child1->SetUpdateRect(gfx::Rect(1, 2));
1007 EmulateDrawingOneFrame(root.get());
1008 child_damage_rect =
1009 child1->render_surface()->damage_tracker()->current_damage_rect();
1010 root_damage_rect =
1011 root->render_surface()->damage_tracker()->current_damage_rect();
1012 EXPECT_TRUE(child_damage_rect.IsEmpty());
1013 EXPECT_TRUE(root_damage_rect.IsEmpty());
1016 TEST_F(DamageTrackerTest, VerifyDamageForReplica) {
1017 scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithTwoSurfaces();
1018 LayerImpl* child1 = root->children()[0];
1019 LayerImpl* grand_child1 = child1->children()[0];
1020 LayerImpl* grand_child2 = child1->children()[1];
1022 // Damage on a surface that has a reflection should cause the target surface
1023 // to receive the surface's damage and the surface's reflected damage.
1025 // For this test case, we modify grand_child2, and add grand_child3 to extend
1026 // the bounds of child1's surface. This way, we can test reflection changes
1027 // without changing content_bounds of the surface.
1028 grand_child2->SetPosition(gfx::PointF(180.f, 180.f));
1030 scoped_ptr<LayerImpl> grand_child3 =
1031 LayerImpl::Create(host_impl_.active_tree(), 6);
1032 grand_child3->SetPosition(gfx::PointF(240.f, 240.f));
1033 grand_child3->SetBounds(gfx::Size(10, 10));
1034 grand_child3->SetDrawsContent(true);
1035 child1->AddChild(grand_child3.Pass());
1037 child1->SetOpacity(0.5f);
1038 EmulateDrawingOneFrame(root.get());
1040 // CASE 1: adding a reflection about the left edge of grand_child1.
1042 ClearDamageForAllSurfaces(root.get());
1044 scoped_ptr<LayerImpl> grand_child1_replica =
1045 LayerImpl::Create(host_impl_.active_tree(), 7);
1046 grand_child1_replica->SetPosition(gfx::PointF());
1047 gfx::Transform reflection;
1048 reflection.Scale3d(-1.0, 1.0, 1.0);
1049 grand_child1_replica->SetTransform(reflection);
1050 grand_child1->SetReplicaLayer(grand_child1_replica.Pass());
1051 grand_child1->SetHasRenderSurface(true);
1053 EmulateDrawingOneFrame(root.get());
1055 gfx::Rect grand_child_damage_rect =
1056 grand_child1->render_surface()->damage_tracker()->current_damage_rect();
1057 gfx::Rect child_damage_rect =
1058 child1->render_surface()->damage_tracker()->current_damage_rect();
1059 gfx::Rect root_damage_rect =
1060 root->render_surface()->damage_tracker()->current_damage_rect();
1062 // The grand_child surface damage should not include its own replica. The
1063 // child surface damage should include the normal and replica surfaces.
1064 EXPECT_EQ(gfx::Rect(6, 8).ToString(), grand_child_damage_rect.ToString());
1065 EXPECT_EQ(gfx::Rect(194, 200, 12, 8).ToString(),
1066 child_damage_rect.ToString());
1067 EXPECT_EQ(gfx::Rect(294, 300, 12, 8).ToString(), root_damage_rect.ToString());
1069 // CASE 2: moving the descendant surface should cause both the original and
1070 // reflected areas to be damaged on the target.
1071 ClearDamageForAllSurfaces(root.get());
1072 gfx::Rect old_content_rect = child1->render_surface()->content_rect();
1073 grand_child1->SetPosition(gfx::PointF(195.f, 205.f));
1074 EmulateDrawingOneFrame(root.get());
1075 ASSERT_EQ(old_content_rect.width(),
1076 child1->render_surface()->content_rect().width());
1077 ASSERT_EQ(old_content_rect.height(),
1078 child1->render_surface()->content_rect().height());
1080 grand_child_damage_rect =
1081 grand_child1->render_surface()->
1082 damage_tracker()->current_damage_rect();
1083 child_damage_rect =
1084 child1->render_surface()->damage_tracker()->current_damage_rect();
1085 root_damage_rect =
1086 root->render_surface()->damage_tracker()->current_damage_rect();
1088 // The child surface damage should include normal and replica surfaces for
1089 // both old and new locations.
1090 // - old location in target space: gfx::Rect(194, 200, 12, 8)
1091 // - new location in target space: gfx::Rect(189, 205, 12, 8)
1092 EXPECT_EQ(gfx::Rect(6, 8).ToString(), grand_child_damage_rect.ToString());
1093 EXPECT_EQ(gfx::Rect(189, 200, 17, 13).ToString(),
1094 child_damage_rect.ToString());
1095 EXPECT_EQ(gfx::Rect(289, 300, 17, 13).ToString(),
1096 root_damage_rect.ToString());
1098 // CASE 3: removing the reflection should cause the entire region including
1099 // reflection to damage the target surface.
1100 ClearDamageForAllSurfaces(root.get());
1101 grand_child1->SetReplicaLayer(nullptr);
1102 grand_child1->SetHasRenderSurface(false);
1103 EmulateDrawingOneFrame(root.get());
1104 ASSERT_EQ(old_content_rect.width(),
1105 child1->render_surface()->content_rect().width());
1106 ASSERT_EQ(old_content_rect.height(),
1107 child1->render_surface()->content_rect().height());
1109 EXPECT_FALSE(grand_child1->render_surface());
1110 child_damage_rect =
1111 child1->render_surface()->damage_tracker()->current_damage_rect();
1112 root_damage_rect =
1113 root->render_surface()->damage_tracker()->current_damage_rect();
1115 EXPECT_EQ(gfx::Rect(189, 205, 12, 8).ToString(),
1116 child_damage_rect.ToString());
1117 EXPECT_EQ(gfx::Rect(289, 305, 12, 8).ToString(), root_damage_rect.ToString());
1120 TEST_F(DamageTrackerTest, VerifyDamageForMask) {
1121 scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithOneSurface();
1122 LayerImpl* child = root->children()[0];
1124 // In the current implementation of the damage tracker, changes to mask
1125 // layers should damage the entire corresponding surface.
1127 ClearDamageForAllSurfaces(root.get());
1129 // Set up the mask layer.
1131 scoped_ptr<LayerImpl> mask_layer =
1132 LayerImpl::Create(host_impl_.active_tree(), 3);
1133 mask_layer->SetPosition(child->position());
1134 mask_layer->SetBounds(child->bounds());
1135 child->SetMaskLayer(mask_layer.Pass());
1136 child->SetHasRenderSurface(true);
1138 LayerImpl* mask_layer = child->mask_layer();
1140 // Add opacity and a grand_child so that the render surface persists even
1141 // after we remove the mask.
1143 scoped_ptr<LayerImpl> grand_child =
1144 LayerImpl::Create(host_impl_.active_tree(), 4);
1145 grand_child->SetPosition(gfx::PointF(2.f, 2.f));
1146 grand_child->SetBounds(gfx::Size(2, 2));
1147 grand_child->SetDrawsContent(true);
1148 child->AddChild(grand_child.Pass());
1150 EmulateDrawingOneFrame(root.get());
1152 // CASE 1: the update_rect on a mask layer should damage the entire target
1153 // surface.
1154 ClearDamageForAllSurfaces(root.get());
1155 mask_layer->SetUpdateRect(gfx::Rect(1, 2, 3, 4));
1156 EmulateDrawingOneFrame(root.get());
1157 gfx::Rect child_damage_rect =
1158 child->render_surface()->damage_tracker()->current_damage_rect();
1159 EXPECT_EQ(gfx::Rect(30, 30).ToString(), child_damage_rect.ToString());
1161 // CASE 2: a property change on the mask layer should damage the entire
1162 // target surface.
1164 // Advance one frame without damage so that we know the damage rect is not
1165 // leftover from the previous case.
1166 ClearDamageForAllSurfaces(root.get());
1167 EmulateDrawingOneFrame(root.get());
1168 child_damage_rect =
1169 child->render_surface()->damage_tracker()->current_damage_rect();
1170 EXPECT_TRUE(child_damage_rect.IsEmpty());
1172 // Then test the property change.
1173 ClearDamageForAllSurfaces(root.get());
1174 mask_layer->SetStackingOrderChanged(true);
1176 EmulateDrawingOneFrame(root.get());
1177 child_damage_rect =
1178 child->render_surface()->damage_tracker()->current_damage_rect();
1179 EXPECT_EQ(gfx::Rect(30, 30).ToString(), child_damage_rect.ToString());
1181 // CASE 3: removing the mask also damages the entire target surface.
1184 // Advance one frame without damage so that we know the damage rect is not
1185 // leftover from the previous case.
1186 ClearDamageForAllSurfaces(root.get());
1187 EmulateDrawingOneFrame(root.get());
1188 child_damage_rect =
1189 child->render_surface()->damage_tracker()->current_damage_rect();
1190 EXPECT_TRUE(child_damage_rect.IsEmpty());
1192 // Then test mask removal.
1193 ClearDamageForAllSurfaces(root.get());
1194 child->SetMaskLayer(nullptr);
1195 ASSERT_TRUE(child->LayerPropertyChanged());
1196 EmulateDrawingOneFrame(root.get());
1198 // Sanity check that a render surface still exists.
1199 ASSERT_TRUE(child->render_surface());
1201 child_damage_rect =
1202 child->render_surface()->damage_tracker()->current_damage_rect();
1203 EXPECT_EQ(gfx::Rect(30, 30).ToString(), child_damage_rect.ToString());
1206 TEST_F(DamageTrackerTest, VerifyDamageForReplicaMask) {
1207 scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithTwoSurfaces();
1208 LayerImpl* child1 = root->children()[0];
1209 LayerImpl* grand_child1 = child1->children()[0];
1211 // Changes to a replica's mask should not damage the original surface,
1212 // because it is not masked. But it does damage the ancestor target surface.
1214 ClearDamageForAllSurfaces(root.get());
1216 // Create a reflection about the left edge of grand_child1.
1218 scoped_ptr<LayerImpl> grand_child1_replica =
1219 LayerImpl::Create(host_impl_.active_tree(), 6);
1220 grand_child1_replica->SetPosition(gfx::PointF());
1221 gfx::Transform reflection;
1222 reflection.Scale3d(-1.0, 1.0, 1.0);
1223 grand_child1_replica->SetTransform(reflection);
1224 grand_child1->SetReplicaLayer(grand_child1_replica.Pass());
1225 grand_child1->SetHasRenderSurface(true);
1227 LayerImpl* grand_child1_replica = grand_child1->replica_layer();
1229 // Set up the mask layer on the replica layer
1231 scoped_ptr<LayerImpl> replica_mask_layer =
1232 LayerImpl::Create(host_impl_.active_tree(), 7);
1233 replica_mask_layer->SetPosition(gfx::PointF());
1234 replica_mask_layer->SetBounds(grand_child1->bounds());
1235 grand_child1_replica->SetMaskLayer(replica_mask_layer.Pass());
1237 LayerImpl* replica_mask_layer = grand_child1_replica->mask_layer();
1239 EmulateDrawingOneFrame(root.get());
1241 // Sanity check that the appropriate render surfaces were created
1242 ASSERT_TRUE(grand_child1->render_surface());
1244 // CASE 1: a property change on the mask should damage only the reflected
1245 // region on the target surface.
1246 ClearDamageForAllSurfaces(root.get());
1247 replica_mask_layer->SetStackingOrderChanged(true);
1248 EmulateDrawingOneFrame(root.get());
1250 gfx::Rect grand_child_damage_rect =
1251 grand_child1->render_surface()->damage_tracker()->current_damage_rect();
1252 gfx::Rect child_damage_rect =
1253 child1->render_surface()->damage_tracker()->current_damage_rect();
1255 EXPECT_TRUE(grand_child_damage_rect.IsEmpty());
1256 EXPECT_EQ(gfx::Rect(194, 200, 6, 8).ToString(), child_damage_rect.ToString());
1258 // CASE 2: removing the replica mask damages only the reflected region on the
1259 // target surface.
1261 ClearDamageForAllSurfaces(root.get());
1262 grand_child1_replica->SetMaskLayer(nullptr);
1263 EmulateDrawingOneFrame(root.get());
1265 grand_child_damage_rect =
1266 grand_child1->render_surface()->damage_tracker()->
1267 current_damage_rect();
1268 child_damage_rect =
1269 child1->render_surface()->damage_tracker()->current_damage_rect();
1271 EXPECT_TRUE(grand_child_damage_rect.IsEmpty());
1272 EXPECT_EQ(gfx::Rect(194, 200, 6, 8).ToString(), child_damage_rect.ToString());
1275 TEST_F(DamageTrackerTest, VerifyDamageForReplicaMaskWithTransformOrigin) {
1276 scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithTwoSurfaces();
1277 LayerImpl* child1 = root->children()[0];
1278 LayerImpl* grand_child1 = child1->children()[0];
1280 // Verify that the correct replica_origin_transform is used for the
1281 // replica_mask.
1282 ClearDamageForAllSurfaces(root.get());
1284 // This is not actually the transform origin point being tested, but by
1285 // convention its
1286 // expected to be the same as the replica's anchor point.
1287 grand_child1->SetTransformOrigin(
1288 gfx::Point3F(grand_child1->bounds().width(), 0.f, 0.f));
1291 scoped_ptr<LayerImpl> grand_child1_replica =
1292 LayerImpl::Create(host_impl_.active_tree(), 6);
1293 grand_child1_replica->SetPosition(gfx::PointF());
1295 // This is the anchor being tested.
1296 grand_child1_replica->SetTransformOrigin(
1297 gfx::Point3F(grand_child1->bounds().width(), 0.f, 0.f));
1298 gfx::Transform reflection;
1299 reflection.Scale3d(-1.0, 1.0, 1.0);
1300 grand_child1_replica->SetTransform(reflection);
1301 grand_child1->SetReplicaLayer(grand_child1_replica.Pass());
1302 grand_child1->SetHasRenderSurface(true);
1304 LayerImpl* grand_child1_replica = grand_child1->replica_layer();
1306 // Set up the mask layer on the replica layer
1308 scoped_ptr<LayerImpl> replica_mask_layer =
1309 LayerImpl::Create(host_impl_.active_tree(), 7);
1310 replica_mask_layer->SetPosition(gfx::PointF());
1311 // Note: this is not the transform origin being tested.
1312 replica_mask_layer->SetBounds(grand_child1->bounds());
1313 grand_child1_replica->SetMaskLayer(replica_mask_layer.Pass());
1315 LayerImpl* replica_mask_layer = grand_child1_replica->mask_layer();
1317 EmulateDrawingOneFrame(root.get());
1319 // Sanity check that the appropriate render surfaces were created
1320 ASSERT_TRUE(grand_child1->render_surface());
1322 // A property change on the replica_mask should damage the reflected region on
1323 // the target surface.
1324 ClearDamageForAllSurfaces(root.get());
1325 replica_mask_layer->SetStackingOrderChanged(true);
1327 EmulateDrawingOneFrame(root.get());
1329 gfx::Rect child_damage_rect =
1330 child1->render_surface()->damage_tracker()->current_damage_rect();
1331 EXPECT_EQ(gfx::Rect(206, 200, 6, 8).ToString(), child_damage_rect.ToString());
1334 TEST_F(DamageTrackerTest, DamageWhenAddedExternally) {
1335 scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithOneSurface();
1336 LayerImpl* child = root->children()[0];
1338 // Case 1: This test ensures that when the tracker is given damage, that
1339 // it is included with any other partial damage.
1341 ClearDamageForAllSurfaces(root.get());
1342 child->SetUpdateRect(gfx::Rect(10, 11, 12, 13));
1343 root->render_surface()->damage_tracker()->AddDamageNextUpdate(
1344 gfx::Rect(15, 16, 32, 33));
1345 EmulateDrawingOneFrame(root.get());
1346 gfx::Rect root_damage_rect =
1347 root->render_surface()->damage_tracker()->current_damage_rect();
1348 EXPECT_EQ(gfx::UnionRects(gfx::Rect(15, 16, 32, 33),
1349 gfx::Rect(100 + 10, 100 + 11, 12, 13)).ToString(),
1350 root_damage_rect.ToString());
1352 // Case 2: An additional sanity check that adding damage works even when
1353 // nothing on the layer tree changed.
1355 ClearDamageForAllSurfaces(root.get());
1356 root->render_surface()->damage_tracker()->AddDamageNextUpdate(
1357 gfx::Rect(30, 31, 14, 15));
1358 EmulateDrawingOneFrame(root.get());
1359 root_damage_rect =
1360 root->render_surface()->damage_tracker()->current_damage_rect();
1361 EXPECT_EQ(gfx::Rect(30, 31, 14, 15).ToString(), root_damage_rect.ToString());
1364 TEST_F(DamageTrackerTest, VerifyDamageForEmptyLayerList) {
1365 // Though it should never happen, its a good idea to verify that the damage
1366 // tracker does not crash when it receives an empty layer_list.
1368 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_.active_tree(), 1);
1369 root->SetHasRenderSurface(true);
1370 root->draw_properties().render_target = root.get();
1372 ASSERT_TRUE(root == root->render_target());
1373 RenderSurfaceImpl* target_surface = root->render_surface();
1375 LayerImplList empty_list;
1376 target_surface->damage_tracker()->UpdateDamageTrackingState(
1377 empty_list,
1378 target_surface->OwningLayerId(),
1379 false,
1380 gfx::Rect(),
1381 NULL,
1382 FilterOperations());
1384 gfx::Rect damage_rect =
1385 target_surface->damage_tracker()->current_damage_rect();
1386 EXPECT_TRUE(damage_rect.IsEmpty());
1389 TEST_F(DamageTrackerTest, VerifyDamageAccumulatesUntilReset) {
1390 // If damage is not cleared, it should accumulate.
1392 scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithOneSurface();
1393 LayerImpl* child = root->children()[0];
1395 ClearDamageForAllSurfaces(root.get());
1396 child->SetUpdateRect(gfx::Rect(10.f, 11.f, 1.f, 2.f));
1397 EmulateDrawingOneFrame(root.get());
1399 // Sanity check damage after the first frame; this isnt the actual test yet.
1400 gfx::Rect root_damage_rect =
1401 root->render_surface()->damage_tracker()->current_damage_rect();
1402 EXPECT_EQ(gfx::Rect(110, 111, 1, 2).ToString(), root_damage_rect.ToString());
1404 // New damage, without having cleared the previous damage, should be unioned
1405 // to the previous one.
1406 child->SetUpdateRect(gfx::Rect(20, 25, 1, 2));
1407 EmulateDrawingOneFrame(root.get());
1408 root_damage_rect =
1409 root->render_surface()->damage_tracker()->current_damage_rect();
1410 EXPECT_EQ(gfx::Rect(110, 111, 11, 16).ToString(),
1411 root_damage_rect.ToString());
1413 // If we notify the damage tracker that we drew the damaged area, then damage
1414 // should be emptied.
1415 root->render_surface()->damage_tracker()->DidDrawDamagedArea();
1416 root_damage_rect =
1417 root->render_surface()->damage_tracker()->current_damage_rect();
1418 EXPECT_TRUE(root_damage_rect.IsEmpty());
1420 // Damage should remain empty even after one frame, since there's yet no new
1421 // damage.
1422 EmulateDrawingOneFrame(root.get());
1423 root_damage_rect =
1424 root->render_surface()->damage_tracker()->current_damage_rect();
1425 EXPECT_TRUE(root_damage_rect.IsEmpty());
1428 TEST_F(DamageTrackerTest, HugeDamageRect) {
1429 // This number is so large that we start losting floating point accuracy.
1430 const int kBigNumber = 900000000;
1431 // Walk over a range to find floating point inaccuracy boundaries that move
1432 // toward the wrong direction.
1433 const int kRange = 5000;
1435 for (int i = 0; i < kRange; ++i) {
1436 scoped_ptr<LayerImpl> root = CreateTestTreeWithOneSurface();
1437 LayerImpl* child = root->children()[0];
1439 gfx::Transform transform;
1440 transform.Translate(-kBigNumber, -kBigNumber);
1442 // The child layer covers (0, 0, i, i) of the viewport,
1443 // but has a huge negative position.
1444 child->SetPosition(gfx::PointF());
1445 child->SetBounds(gfx::Size(kBigNumber + i, kBigNumber + i));
1446 child->SetTransform(transform);
1447 EmulateDrawingOneFrame(root.get());
1449 // The expected damage should cover the visible part of the child layer,
1450 // which is (0, 0, i, i) in the viewport.
1451 gfx::Rect root_damage_rect =
1452 root->render_surface()->damage_tracker()->current_damage_rect();
1453 gfx::Rect damage_we_care_about = gfx::Rect(i, i);
1454 EXPECT_LE(damage_we_care_about.right(), root_damage_rect.right());
1455 EXPECT_LE(damage_we_care_about.bottom(), root_damage_rect.bottom());
1459 } // namespace
1460 } // namespace cc