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.
4
5#include "cc/trees/damage_tracker.h"
6
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"
21
22namespace cc {
23namespace {
24
25void 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());
32
33  FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(root);
34  LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs(
35      root, root->bounds(), render_surface_layer_list);
36  LayerTreeHostCommon::CalculateDrawProperties(&inputs);
37}
38
39void ClearDamageForAllSurfaces(LayerImpl* layer) {
40  if (layer->render_surface())
41    layer->render_surface()->damage_tracker()->DidDrawDamagedArea();
42
43  // Recursively clear damage for any existing surface.
44  for (size_t i = 0; i < layer->children().size(); ++i)
45    ClearDamageForAllSurfaces(layer->children()[i]);
46}
47
48void 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.
54
55  LayerImplList render_surface_layer_list;
56  ExecuteCalculateDrawProperties(root, &render_surface_layer_list);
57
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());
70  }
71
72  root->ResetAllChangeTrackingForSubtree();
73}
74
75class DamageTrackerTest : public testing::Test {
76 public:
77  DamageTrackerTest() : host_impl_(&proxy_, &shared_bitmap_manager_) {}
78
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);
84
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));
91
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());
97
98    return root.Pass();
99  }
100
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.
105
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);
116
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));
123
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);
134
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);
139
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);
144
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);
149
150    child1->AddChild(grand_child1.Pass());
151    child1->AddChild(grand_child2.Pass());
152    root->AddChild(child1.Pass());
153    root->AddChild(child2.Pass());
154
155    return root.Pass();
156  }
157
158  scoped_ptr<LayerImpl> CreateAndSetUpTestTreeWithOneSurface() {
159    scoped_ptr<LayerImpl> root = CreateTestTreeWithOneSurface();
160
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());
164
165    return root.Pass();
166  }
167
168  scoped_ptr<LayerImpl> CreateAndSetUpTestTreeWithTwoSurfaces() {
169    scoped_ptr<LayerImpl> root = CreateTestTreeWithTwoSurfaces();
170
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());
174
175    return root.Pass();
176  }
177
178 protected:
179  FakeImplProxy proxy_;
180  TestSharedBitmapManager shared_bitmap_manager_;
181  FakeLayerTreeHostImpl host_impl_;
182};
183
184TEST_F(DamageTrackerTest, SanityCheckTestTreeWithOneSurface) {
185  // Sanity check that the simple test tree will actually produce the expected
186  // render surfaces and layer lists.
187
188  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithOneSurface();
189
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());
193
194  gfx::Rect root_damage_rect =
195      root->render_surface()->damage_tracker()->current_damage_rect();
196
197  EXPECT_EQ(gfx::Rect(500, 500).ToString(), root_damage_rect.ToString());
198}
199
200TEST_F(DamageTrackerTest, SanityCheckTestTreeWithTwoSurfaces) {
201  // Sanity check that the complex test tree will actually produce the expected
202  // render surfaces and layer lists.
203
204  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithTwoSurfaces();
205
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();
212
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());
217
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());
223}
224
225TEST_F(DamageTrackerTest, VerifyDamageForUpdateRects) {
226  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithOneSurface();
227  LayerImpl* child = root->children()[0];
228
229  // CASE 1: Setting the update rect should cause the corresponding damage to
230  //         the surface.
231  ClearDamageForAllSurfaces(root.get());
232  child->SetUpdateRect(gfx::RectF(10.f, 11.f, 12.f, 13.f));
233  EmulateDrawingOneFrame(root.get());
234
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());
241
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::RectF(10.f, 11.f, 12.f, 13.f));
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());
251
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::RectF(20.f, 25.f, 1.f, 2.f));
256  EmulateDrawingOneFrame(root.get());
257
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());
263}
264
265TEST_F(DamageTrackerTest, VerifyDamageForLayerDamageRects) {
266  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithOneSurface();
267  LayerImpl* child = root->children()[0];
268
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());
274
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)));
280
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)));
289
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());
295
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)));
301
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());
308
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)));
315}
316
317TEST_F(DamageTrackerTest, VerifyDamageForLayerUpdateAndDamageRects) {
318  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithOneSurface();
319  LayerImpl* child = root->children()[0];
320
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::RectF(15.f, 16.f, 14.f, 10.f));
326  EmulateDrawingOneFrame(root.get());
327
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)));
334
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::RectF(10.f, 11.f, 14.f, 15.f));
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)));
344
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::RectF(5.f, 10.f, 7.f, 8.f));
350  EmulateDrawingOneFrame(root.get());
351
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)));
357}
358
359TEST_F(DamageTrackerTest, VerifyDamageForPropertyChanges) {
360  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithOneSurface();
361  LayerImpl* child = root->children()[0];
362
363  // CASE 1: The layer's property changed flag takes priority over update rect.
364  //
365  ClearDamageForAllSurfaces(root.get());
366  child->SetUpdateRect(gfx::RectF(10.f, 11.f, 12.f, 13.f));
367  child->SetOpacity(0.5f);
368  EmulateDrawingOneFrame(root.get());
369
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());
374
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());
380
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.
384
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());
392
393  // Then, test the actual layer movement.
394  ClearDamageForAllSurfaces(root.get());
395  child->SetPosition(gfx::PointF(200.f, 230.f));
396  EmulateDrawingOneFrame(root.get());
397
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);
403}
404
405TEST_F(DamageTrackerTest, VerifyDamageForTransformedLayer) {
406  // If a layer is transformed, the damage rect should still enclose the entire
407  // transformed layer.
408
409  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithOneSurface();
410  LayerImpl* child = root->children()[0];
411
412  gfx::Transform rotation;
413  rotation.Rotate(45.0);
414
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());
420
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());
426
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());
432
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());
444}
445
446TEST_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.
450  //
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.
457  //
458
459  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithOneSurface();
460  LayerImpl* child = root->children()[0];
461
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);
467
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());
474
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);
481
482  // Damage the child without moving it.
483  ClearDamageForAllSurfaces(root.get());
484  child->SetOpacity(0.5f);
485  EmulateDrawingOneFrame(root.get());
486
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));
494}
495
496TEST_F(DamageTrackerTest, VerifyDamageForBlurredSurface) {
497  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithTwoSurfaces();
498  LayerImpl* surface = root->children()[0];
499  LayerImpl* child = surface->children()[0];
500
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);
505
506  // Setting the filter will damage the whole surface.
507  ClearDamageForAllSurfaces(root.get());
508  surface->SetFilters(filters);
509  EmulateDrawingOneFrame(root.get());
510
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::RectF(1.f, 2.f, 3.f, 4.f));
515  EmulateDrawingOneFrame(root.get());
516
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);
522
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());
528}
529
530TEST_F(DamageTrackerTest, VerifyDamageForImageFilter) {
531  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithOneSurface();
532  LayerImpl* child = root->children()[0];
533  gfx::Rect root_damage_rect, child_damage_rect;
534
535  // Allow us to set damage on child too.
536  child->SetDrawsContent(true);
537
538  skia::RefPtr<SkImageFilter> filter = skia::AdoptRef(
539      SkBlurImageFilter::Create(SkIntToScalar(2), SkIntToScalar(2)));
540  FilterOperations filters;
541  filters.Append(FilterOperation::CreateReferenceFilter(filter));
542
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());
554
555  // CASE 1: Setting the update rect should damage the whole surface (for now)
556  ClearDamageForAllSurfaces(root.get());
557  child->SetUpdateRect(gfx::RectF(1.f, 1.f));
558  EmulateDrawingOneFrame(root.get());
559
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());
567}
568
569TEST_F(DamageTrackerTest, VerifyDamageForBackgroundBlurredChild) {
570  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithTwoSurfaces();
571  LayerImpl* child1 = root->children()[0];
572  LayerImpl* child2 = root->children()[1];
573
574  // Allow us to set damage on child1 too.
575  child1->SetDrawsContent(true);
576
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);
581
582  // Setting the filter will damage the whole surface.
583  ClearDamageForAllSurfaces(root.get());
584  child1->SetBackgroundFilters(filters);
585  EmulateDrawingOneFrame(root.get());
586
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::RectF(297.f, 297.f, 2.f, 2.f));
592  EmulateDrawingOneFrame(root.get());
593
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);
600
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());
606
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::RectF(297.f, 297.f, 30.f, 30.f));
613  EmulateDrawingOneFrame(root.get());
614
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);
621
622  expected_damage_rect.Inset(-outset_left,
623                             -outset_top,
624                             0,
625                             0);
626  EXPECT_EQ(expected_damage_rect.ToString(), root_damage_rect.ToString());
627
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::RectF(30.f, 30.f, 2.f, 2.f));
632  EmulateDrawingOneFrame(root.get());
633
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);
639
640  EXPECT_EQ(expected_damage_rect.ToString(), root_damage_rect.ToString());
641
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::RectF(99.f, 99.f, 1.f, 1.f));
647  EmulateDrawingOneFrame(root.get());
648
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);
655
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());
661
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::RectF(0.f, 0.f, 1.f, 1.f));
666  EmulateDrawingOneFrame(root.get());
667
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);
673
674  EXPECT_EQ(expected_damage_rect.ToString(), root_damage_rect.ToString());
675
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::RectF(0.f, 0.f, 1.f, 1.f));
681  EmulateDrawingOneFrame(root.get());
682
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);
688
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());
694}
695
696TEST_F(DamageTrackerTest, VerifyDamageForAddingAndRemovingLayer) {
697  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithOneSurface();
698  LayerImpl* child1 = root->children()[0];
699
700  // CASE 1: Adding a new layer should cause the appropriate damage.
701  //
702  ClearDamageForAllSurfaces(root.get());
703  {
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());
711  }
712  EmulateDrawingOneFrame(root.get());
713
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());
717
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());
721
722  // CASE 2: If the layer is removed, its entire old layer becomes exposed, not
723  //         just the last update rect.
724
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());
729
730  root_damage_rect =
731          root->render_surface()->damage_tracker()->current_damage_rect();
732  EXPECT_TRUE(root_damage_rect.IsEmpty());
733
734  // Then, test removing child1.
735  root->RemoveChild(child1);
736  child1 = NULL;
737  EmulateDrawingOneFrame(root.get());
738
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());
743}
744
745TEST_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.
748
749  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithOneSurface();
750
751  ClearDamageForAllSurfaces(root.get());
752  {
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());
766  }
767  EmulateDrawingOneFrame(root.get());
768
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());
772
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());
776}
777
778TEST_F(DamageTrackerTest, VerifyDamageForMultipleLayers) {
779  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithOneSurface();
780  LayerImpl* child1 = root->children()[0];
781
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());
785  {
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());
793  }
794  LayerImpl* child2 = root->children()[1];
795  EmulateDrawingOneFrame(root.get());
796
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::RectF(0.f, 0.f, 1.f, 2.f));
802  child2->SetUpdateRect(gfx::RectF(0.f, 0.f, 3.f, 4.f));
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());
808}
809
810TEST_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;
817
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());
829
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());
847}
848
849TEST_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.
853
854  // This is a tricky case, since only the first grand_child changes, but the
855  // entire surface should be marked dirty.
856
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;
862
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();
870
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());
875
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());
881}
882
883TEST_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.
889
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.
894
895  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithTwoSurfaces();
896  LayerImpl* child1 = root->children()[0];
897  gfx::Rect child_damage_rect;
898  gfx::Rect root_damage_rect;
899
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();
907
908  // The new surface bounds should be damaged entirely.
909  EXPECT_EQ(gfx::Rect(190, 190, 16, 18).ToString(),
910            child_damage_rect.ToString());
911
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());
918}
919
920TEST_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;
925
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());
932
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());
936
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());
941
942  // CASE 2: If a descendant surface appears, its entire old area becomes
943  //         exposed.
944
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());
952
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());
958
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());
963
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());
972}
973
974TEST_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;
979
980  // CASE 1: If nothing changes, the damage rect should be empty.
981  //
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());
990
991  // CASE 2: If nothing changes twice in a row, the damage rect should still be
992  //         empty.
993  //
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());
1002}
1003
1004TEST_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;
1009
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::RectF(0.f, 0.f, 1.f, 2.f));
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());
1021}
1022
1023TEST_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];
1028
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.
1031
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));
1036  {
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());
1044  }
1045  child1->SetOpacity(0.5f);
1046  EmulateDrawingOneFrame(root.get());
1047
1048  // CASE 1: adding a reflection about the left edge of grand_child1.
1049  //
1050  ClearDamageForAllSurfaces(root.get());
1051  {
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());
1059  }
1060  EmulateDrawingOneFrame(root.get());
1061
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();
1068
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());
1075
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());
1086
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();
1094
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());
1104
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(scoped_ptr<LayerImpl>());
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());
1114
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();
1120
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());
1124}
1125
1126TEST_F(DamageTrackerTest, VerifyDamageForMask) {
1127  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithOneSurface();
1128  LayerImpl* child = root->children()[0];
1129
1130  // In the current implementation of the damage tracker, changes to mask
1131  // layers should damage the entire corresponding surface.
1132
1133  ClearDamageForAllSurfaces(root.get());
1134
1135  // Set up the mask layer.
1136  {
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());
1143  }
1144  LayerImpl* mask_layer = child->mask_layer();
1145
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);
1149  {
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());
1157  }
1158  EmulateDrawingOneFrame(root.get());
1159
1160  // Sanity check that a new surface was created for the child.
1161  ASSERT_TRUE(child->render_surface());
1162
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::RectF(1.f, 2.f, 3.f, 4.f));
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());
1171
1172  // CASE 2: a property change on the mask layer should damage the entire
1173  //         target surface.
1174
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());
1182
1183  // Then test the property change.
1184  ClearDamageForAllSurfaces(root.get());
1185  mask_layer->SetStackingOrderChanged(true);
1186
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());
1191
1192  // CASE 3: removing the mask also damages the entire target surface.
1193  //
1194
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());
1202
1203  // Then test mask removal.
1204  ClearDamageForAllSurfaces(root.get());
1205  child->SetMaskLayer(scoped_ptr<LayerImpl>());
1206  ASSERT_TRUE(child->LayerPropertyChanged());
1207  EmulateDrawingOneFrame(root.get());
1208
1209  // Sanity check that a render surface still exists.
1210  ASSERT_TRUE(child->render_surface());
1211
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());
1215}
1216
1217TEST_F(DamageTrackerTest, VerifyDamageForReplicaMask) {
1218  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithTwoSurfaces();
1219  LayerImpl* child1 = root->children()[0];
1220  LayerImpl* grand_child1 = child1->children()[0];
1221
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.
1224
1225  ClearDamageForAllSurfaces(root.get());
1226
1227  // Create a reflection about the left edge of grand_child1.
1228  {
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());
1236  }
1237  LayerImpl* grand_child1_replica = grand_child1->replica_layer();
1238
1239  // Set up the mask layer on the replica layer
1240  {
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());
1247  }
1248  LayerImpl* replica_mask_layer = grand_child1_replica->mask_layer();
1249
1250  EmulateDrawingOneFrame(root.get());
1251
1252  // Sanity check that the appropriate render surfaces were created
1253  ASSERT_TRUE(grand_child1->render_surface());
1254
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());
1260
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();
1265
1266  EXPECT_TRUE(grand_child_damage_rect.IsEmpty());
1267  EXPECT_EQ(gfx::Rect(194, 200, 6, 8).ToString(), child_damage_rect.ToString());
1268
1269  // CASE 2: removing the replica mask damages only the reflected region on the
1270  //         target surface.
1271  //
1272  ClearDamageForAllSurfaces(root.get());
1273  grand_child1_replica->SetMaskLayer(scoped_ptr<LayerImpl>());
1274  EmulateDrawingOneFrame(root.get());
1275
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();
1281
1282  EXPECT_TRUE(grand_child_damage_rect.IsEmpty());
1283  EXPECT_EQ(gfx::Rect(194, 200, 6, 8).ToString(), child_damage_rect.ToString());
1284}
1285
1286TEST_F(DamageTrackerTest, VerifyDamageForReplicaMaskWithTransformOrigin) {
1287  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithTwoSurfaces();
1288  LayerImpl* child1 = root->children()[0];
1289  LayerImpl* grand_child1 = child1->children()[0];
1290
1291  // Verify that the correct replica_origin_transform is used for the
1292  // replica_mask.
1293  ClearDamageForAllSurfaces(root.get());
1294
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));
1300
1301  {
1302    scoped_ptr<LayerImpl> grand_child1_replica =
1303            LayerImpl::Create(host_impl_.active_tree(), 6);
1304    grand_child1_replica->SetPosition(gfx::PointF());
1305
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());
1313  }
1314  LayerImpl* grand_child1_replica = grand_child1->replica_layer();
1315
1316  // Set up the mask layer on the replica layer
1317  {
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());
1325  }
1326  LayerImpl* replica_mask_layer = grand_child1_replica->mask_layer();
1327
1328  EmulateDrawingOneFrame(root.get());
1329
1330  // Sanity check that the appropriate render surfaces were created
1331  ASSERT_TRUE(grand_child1->render_surface());
1332
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);
1337
1338  EmulateDrawingOneFrame(root.get());
1339
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());
1343}
1344
1345TEST_F(DamageTrackerTest, DamageWhenAddedExternally) {
1346  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithOneSurface();
1347  LayerImpl* child = root->children()[0];
1348
1349  // Case 1: This test ensures that when the tracker is given damage, that
1350  //         it is included with any other partial damage.
1351  //
1352  ClearDamageForAllSurfaces(root.get());
1353  child->SetUpdateRect(gfx::RectF(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());
1362
1363  // Case 2: An additional sanity check that adding damage works even when
1364  //         nothing on the layer tree changed.
1365  //
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());
1373}
1374
1375TEST_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.
1378
1379  scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_.active_tree(), 1);
1380  root->CreateRenderSurface();
1381
1382  ASSERT_TRUE(root == root->render_target());
1383  RenderSurfaceImpl* target_surface = root->render_surface();
1384
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());
1393
1394  gfx::Rect damage_rect =
1395      target_surface->damage_tracker()->current_damage_rect();
1396  EXPECT_TRUE(damage_rect.IsEmpty());
1397}
1398
1399TEST_F(DamageTrackerTest, VerifyDamageAccumulatesUntilReset) {
1400  // If damage is not cleared, it should accumulate.
1401
1402  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithOneSurface();
1403  LayerImpl* child = root->children()[0];
1404
1405  ClearDamageForAllSurfaces(root.get());
1406  child->SetUpdateRect(gfx::Rect(10.f, 11.f, 1.f, 2.f));
1407  EmulateDrawingOneFrame(root.get());
1408
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());
1413
1414  // New damage, without having cleared the previous damage, should be unioned
1415  // to the previous one.
1416  child->SetUpdateRect(gfx::RectF(20.f, 25.f, 1.f, 2.f));
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());
1422
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());
1429
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());
1436}
1437
1438TEST_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;
1444
1445  for (int i = 0; i < kRange; ++i) {
1446    scoped_ptr<LayerImpl> root = CreateTestTreeWithOneSurface();
1447    LayerImpl* child = root->children()[0];
1448
1449    gfx::Transform transform;
1450    transform.Translate(-kBigNumber, -kBigNumber);
1451
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());
1459
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());
1467  }
1468}
1469
1470}  // namespace
1471}  // namespace cc
1472