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