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