12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2011 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/trees/damage_tracker.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/base/math_util.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/layers/layer_impl.h"
9eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "cc/output/filter_operation.h"
10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "cc/output/filter_operations.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/test/fake_impl_proxy.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/test/fake_layer_tree_host_impl.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/test/geometry_test_utils.h"
1423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "cc/test/test_shared_bitmap_manager.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/trees/layer_tree_host_common.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/trees/single_thread_proxy.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/skia/include/effects/SkBlurImageFilter.h"
19c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "ui/gfx/geometry/quad_f.h"
20c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "ui/gfx/geometry/rect_conversions.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace cc {
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
25558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochvoid ExecuteCalculateDrawProperties(LayerImpl* root,
2646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                    LayerImplList* render_surface_layer_list) {
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Sanity check: The test itself should create the root layer's render
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //               surface, so that the surface (and its damage tracker) can
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //               persist across multiple calls to this function.
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(root->render_surface());
3146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ASSERT_FALSE(render_surface_layer_list->size());
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(root);
34558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs(
3546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      root, root->bounds(), render_surface_layer_list);
36558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  LayerTreeHostCommon::CalculateDrawProperties(&inputs);
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ClearDamageForAllSurfaces(LayerImpl* layer) {
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (layer->render_surface())
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    layer->render_surface()->damage_tracker()->DidDrawDamagedArea();
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Recursively clear damage for any existing surface.
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < layer->children().size(); ++i)
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ClearDamageForAllSurfaces(layer->children()[i]);
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void EmulateDrawingOneFrame(LayerImpl* root) {
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This emulates only steps that are relevant to testing the damage tracker:
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //   1. computing the render passes and layerlists
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //   2. updating all damage trackers in the correct order
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //   3. resetting all update_rects and property_changed flags for all layers
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //      and surfaces.
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LayerImplList render_surface_layer_list;
5646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ExecuteCalculateDrawProperties(root, &render_surface_layer_list);
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Iterate back-to-front, so that damage correctly propagates from descendant
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // surfaces to ancestors.
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int i = render_surface_layer_list.size() - 1; i >= 0; --i) {
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    RenderSurfaceImpl* target_surface =
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            render_surface_layer_list[i]->render_surface();
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    target_surface->damage_tracker()->UpdateDamageTrackingState(
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        target_surface->layer_list(),
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        target_surface->OwningLayerId(),
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        target_surface->SurfacePropertyChangedOnlyFromDescendant(),
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        target_surface->content_rect(),
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        render_surface_layer_list[i]->mask_layer(),
6968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        render_surface_layer_list[i]->filters());
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root->ResetAllChangeTrackingForSubtree();
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class DamageTrackerTest : public testing::Test {
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
7723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DamageTrackerTest() : host_impl_(&proxy_, &shared_bitmap_manager_) {}
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<LayerImpl> CreateTestTreeWithOneSurface() {
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<LayerImpl> root =
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            LayerImpl::Create(host_impl_.active_tree(), 1);
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<LayerImpl> child =
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            LayerImpl::Create(host_impl_.active_tree(), 2);
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    root->SetPosition(gfx::PointF());
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    root->SetBounds(gfx::Size(500, 500));
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    root->SetContentBounds(gfx::Size(500, 500));
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    root->SetDrawsContent(true);
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    root->CreateRenderSurface();
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    root->render_surface()->SetContentRect(gfx::Rect(0, 0, 500, 500));
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    child->SetPosition(gfx::PointF(100.f, 100.f));
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    child->SetBounds(gfx::Size(30, 30));
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    child->SetContentBounds(gfx::Size(30, 30));
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    child->SetDrawsContent(true);
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    root->AddChild(child.Pass());
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return root.Pass();
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<LayerImpl> CreateTestTreeWithTwoSurfaces() {
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // This test tree has two render surfaces: one for the root, and one for
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // child1. Additionally, the root has a second child layer, and child1 has
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // two children of its own.
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<LayerImpl> root =
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            LayerImpl::Create(host_impl_.active_tree(), 1);
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<LayerImpl> child1 =
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            LayerImpl::Create(host_impl_.active_tree(), 2);
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<LayerImpl> child2 =
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            LayerImpl::Create(host_impl_.active_tree(), 3);
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<LayerImpl> grand_child1 =
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            LayerImpl::Create(host_impl_.active_tree(), 4);
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<LayerImpl> grand_child2 =
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            LayerImpl::Create(host_impl_.active_tree(), 5);
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    root->SetPosition(gfx::PointF());
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    root->SetBounds(gfx::Size(500, 500));
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    root->SetContentBounds(gfx::Size(500, 500));
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    root->SetDrawsContent(true);
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    root->CreateRenderSurface();
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    root->render_surface()->SetContentRect(gfx::Rect(0, 0, 500, 500));
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    child1->SetPosition(gfx::PointF(100.f, 100.f));
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    child1->SetBounds(gfx::Size(30, 30));
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    child1->SetContentBounds(gfx::Size(30, 30));
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // With a child that draws_content, opacity will cause the layer to create
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // its own RenderSurface. This layer does not draw, but is intended to
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // create its own RenderSurface. TODO: setting opacity and
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // ForceRenderSurface may be redundant here.
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    child1->SetOpacity(0.5f);
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    child1->SetDrawsContent(false);
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    child1->SetForceRenderSurface(true);
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    child2->SetPosition(gfx::PointF(11.f, 11.f));
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    child2->SetBounds(gfx::Size(18, 18));
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    child2->SetContentBounds(gfx::Size(18, 18));
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    child2->SetDrawsContent(true);
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    grand_child1->SetPosition(gfx::PointF(200.f, 200.f));
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    grand_child1->SetBounds(gfx::Size(6, 8));
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    grand_child1->SetContentBounds(gfx::Size(6, 8));
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    grand_child1->SetDrawsContent(true);
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    grand_child2->SetPosition(gfx::PointF(190.f, 190.f));
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    grand_child2->SetBounds(gfx::Size(6, 8));
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    grand_child2->SetContentBounds(gfx::Size(6, 8));
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    grand_child2->SetDrawsContent(true);
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    child1->AddChild(grand_child1.Pass());
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    child1->AddChild(grand_child2.Pass());
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    root->AddChild(child1.Pass());
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    root->AddChild(child2.Pass());
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return root.Pass();
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<LayerImpl> CreateAndSetUpTestTreeWithOneSurface() {
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<LayerImpl> root = CreateTestTreeWithOneSurface();
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Setup includes going past the first frame which always damages
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // everything, so that we can actually perform specific tests.
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EmulateDrawingOneFrame(root.get());
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return root.Pass();
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<LayerImpl> CreateAndSetUpTestTreeWithTwoSurfaces() {
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<LayerImpl> root = CreateTestTreeWithTwoSurfaces();
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Setup includes going past the first frame which always damages
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // everything, so that we can actually perform specific tests.
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EmulateDrawingOneFrame(root.get());
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return root.Pass();
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) protected:
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FakeImplProxy proxy_;
18023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  TestSharedBitmapManager shared_bitmap_manager_;
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FakeLayerTreeHostImpl host_impl_;
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(DamageTrackerTest, SanityCheckTestTreeWithOneSurface) {
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Sanity check that the simple test tree will actually produce the expected
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // render surfaces and layer lists.
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithOneSurface();
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(2u, root->render_surface()->layer_list().size());
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(1, root->render_surface()->layer_list()[0]->id());
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(2, root->render_surface()->layer_list()[1]->id());
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
194c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect root_damage_rect =
195c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      root->render_surface()->damage_tracker()->current_damage_rect();
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
197c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(500, 500).ToString(), root_damage_rect.ToString());
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(DamageTrackerTest, SanityCheckTestTreeWithTwoSurfaces) {
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Sanity check that the complex test tree will actually produce the expected
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // render surfaces and layer lists.
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithTwoSurfaces();
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerImpl* child1 = root->children()[0];
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerImpl* child2 = root->children()[1];
208c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect child_damage_rect =
209c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      child1->render_surface()->damage_tracker()->current_damage_rect();
210c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect root_damage_rect =
211c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      root->render_surface()->damage_tracker()->current_damage_rect();
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(child1->render_surface());
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(child2->render_surface());
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(3u, root->render_surface()->layer_list().size());
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(2u, child1->render_surface()->layer_list().size());
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The render surface for child1 only has a content_rect that encloses
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // grand_child1 and grand_child2, because child1 does not draw content.
220c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(190, 190, 16, 18).ToString(),
221c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            child_damage_rect.ToString());
222c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(500, 500).ToString(), root_damage_rect.ToString());
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(DamageTrackerTest, VerifyDamageForUpdateRects) {
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithOneSurface();
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerImpl* child = root->children()[0];
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // CASE 1: Setting the update rect should cause the corresponding damage to
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //         the surface.
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  child->SetUpdateRect(gfx::RectF(10.f, 11.f, 12.f, 13.f));
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Damage position on the surface should be: position of update_rect (10, 11)
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // relative to the child (100, 100).
237c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect root_damage_rect =
238c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      root->render_surface()->damage_tracker()->current_damage_rect();
239c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(110, 111, 12, 13).ToString(),
240c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            root_damage_rect.ToString());
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // CASE 2: The same update rect twice in a row still produces the same
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //         damage.
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  child->SetUpdateRect(gfx::RectF(10.f, 11.f, 12.f, 13.f));
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root_damage_rect =
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          root->render_surface()->damage_tracker()->current_damage_rect();
249c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(110, 111, 12, 13).ToString(),
250c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            root_damage_rect.ToString());
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // CASE 3: Setting a different update rect should cause damage on the new
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //         update region, but no additional exposed old region.
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  child->SetUpdateRect(gfx::RectF(20.f, 25.f, 1.f, 2.f));
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Damage position on the surface should be: position of update_rect (20, 25)
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // relative to the child (100, 100).
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root_damage_rect =
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          root->render_surface()->damage_tracker()->current_damage_rect();
262c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(120, 125, 1, 2).ToString(), root_damage_rect.ToString());
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST_F(DamageTrackerTest, VerifyDamageForLayerDamageRects) {
2665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithOneSurface();
2675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  LayerImpl* child = root->children()[0];
2685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // CASE 1: Adding the layer damage rect should cause the corresponding damage
2705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // to the surface.
2715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ClearDamageForAllSurfaces(root.get());
2725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  child->AddDamageRect(gfx::RectF(10.f, 11.f, 12.f, 13.f));
2735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EmulateDrawingOneFrame(root.get());
2745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Damage position on the surface should be: position of layer damage_rect
2765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // (10, 11) relative to the child (100, 100).
2775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  gfx::Rect root_damage_rect =
2785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      root->render_surface()->damage_tracker()->current_damage_rect();
2795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ(true, root_damage_rect.Contains(gfx::Rect(110, 111, 12, 13)));
2805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // CASE 2: The same layer damage rect twice in a row still produces the same
2825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // damage.
2835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ClearDamageForAllSurfaces(root.get());
2845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  child->AddDamageRect(gfx::RectF(10.f, 11.f, 12.f, 13.f));
2855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EmulateDrawingOneFrame(root.get());
2865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  root_damage_rect =
2875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      root->render_surface()->damage_tracker()->current_damage_rect();
2885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ(true, root_damage_rect.Contains(gfx::Rect(110, 111, 12, 13)));
2895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // CASE 3: Adding a different layer damage rect should cause damage on the
2915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // new damaged region, but no additional exposed old region.
2925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ClearDamageForAllSurfaces(root.get());
2935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  child->AddDamageRect(gfx::RectF(20.f, 25.f, 1.f, 2.f));
2945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EmulateDrawingOneFrame(root.get());
2955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Damage position on the surface should be: position of layer damage_rect
2975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // (20, 25) relative to the child (100, 100).
2985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  root_damage_rect =
2995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      root->render_surface()->damage_tracker()->current_damage_rect();
3005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ(true, root_damage_rect.Contains(gfx::Rect(120, 125, 1, 2)));
3015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // CASE 4: Adding multiple layer damage rects should cause a unified
3035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // damage on root damage rect.
3045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ClearDamageForAllSurfaces(root.get());
3055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  child->AddDamageRect(gfx::RectF(20.f, 25.f, 1.f, 2.f));
3065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  child->AddDamageRect(gfx::RectF(10.f, 15.f, 3.f, 4.f));
3075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EmulateDrawingOneFrame(root.get());
3085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Damage position on the surface should be: position of layer damage_rect
3105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // (20, 25) relative to the child (100, 100).
3115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  root_damage_rect =
3125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      root->render_surface()->damage_tracker()->current_damage_rect();
3135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ(true, root_damage_rect.Contains(gfx::Rect(120, 125, 1, 2)));
3145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ(true, root_damage_rect.Contains(gfx::Rect(110, 115, 3, 4)));
3155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
3165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST_F(DamageTrackerTest, VerifyDamageForLayerUpdateAndDamageRects) {
3185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithOneSurface();
3195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  LayerImpl* child = root->children()[0];
3205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // CASE 1: Adding the layer damage rect and update rect should cause the
3225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // corresponding damage to the surface.
3235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ClearDamageForAllSurfaces(root.get());
3245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  child->AddDamageRect(gfx::RectF(5.f, 6.f, 12.f, 13.f));
3255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  child->SetUpdateRect(gfx::RectF(15.f, 16.f, 14.f, 10.f));
3265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EmulateDrawingOneFrame(root.get());
3275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Damage position on the surface should be: position of unified layer
3295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // damage_rect and update rect (5, 6)
3305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // relative to the child (100, 100).
3315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  gfx::Rect root_damage_rect =
3325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      root->render_surface()->damage_tracker()->current_damage_rect();
3335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ(true, root_damage_rect.Contains(gfx::Rect(105, 106, 24, 20)));
3345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // CASE 2: The same layer damage rect and update rect twice in a row still
3365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // produces the same damage.
3375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ClearDamageForAllSurfaces(root.get());
3385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  child->AddDamageRect(gfx::RectF(10.f, 11.f, 12.f, 13.f));
3395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  child->SetUpdateRect(gfx::RectF(10.f, 11.f, 14.f, 15.f));
3405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EmulateDrawingOneFrame(root.get());
3415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  root_damage_rect =
3425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      root->render_surface()->damage_tracker()->current_damage_rect();
3435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ(true, root_damage_rect.Contains(gfx::Rect(110, 111, 14, 15)));
3445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // CASE 3: Adding a different layer damage rect and update rect should cause
3465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // damage on the new damaged region, but no additional exposed old region.
3475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ClearDamageForAllSurfaces(root.get());
3485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  child->AddDamageRect(gfx::RectF(20.f, 25.f, 2.f, 3.f));
3495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  child->SetUpdateRect(gfx::RectF(5.f, 10.f, 7.f, 8.f));
3505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EmulateDrawingOneFrame(root.get());
3515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Damage position on the surface should be: position of unified layer damage
3535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // rect and update rect (5, 10) relative to the child (100, 100).
3545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  root_damage_rect =
3555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      root->render_surface()->damage_tracker()->current_damage_rect();
3565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ(true, root_damage_rect.Contains(gfx::Rect(105, 110, 17, 18)));
3575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
3585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(DamageTrackerTest, VerifyDamageForPropertyChanges) {
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithOneSurface();
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerImpl* child = root->children()[0];
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // CASE 1: The layer's property changed flag takes priority over update rect.
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  child->SetUpdateRect(gfx::RectF(10.f, 11.f, 12.f, 13.f));
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  child->SetOpacity(0.5f);
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Sanity check - we should not have accidentally created a separate render
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // surface for the translucent layer.
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_FALSE(child->render_surface());
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(2u, root->render_surface()->layer_list().size());
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Damage should be the entire child layer in target_surface space.
376c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect expected_rect = gfx::Rect(100, 100, 30, 30);
377c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect root_damage_rect =
378c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      root->render_surface()->damage_tracker()->current_damage_rect();
379c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(expected_rect.ToString(), root_damage_rect.ToString());
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // CASE 2: If a layer moves due to property change, it damages both the new
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //         location and the old (exposed) location. The old location is the
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //         entire old layer, not just the update_rect.
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Cycle one frame of no change, just to sanity check that the next rect is
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // not because of the old damage state.
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root_damage_rect =
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          root->render_surface()->damage_tracker()->current_damage_rect();
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(root_damage_rect.IsEmpty());
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Then, test the actual layer movement.
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  child->SetPosition(gfx::PointF(200.f, 230.f));
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Expect damage to be the combination of the previous one and the new one.
399c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  expected_rect.Union(gfx::Rect(200, 230, 30, 30));
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root_damage_rect =
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          root->render_surface()->damage_tracker()->current_damage_rect();
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FLOAT_RECT_EQ(expected_rect, root_damage_rect);
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(DamageTrackerTest, VerifyDamageForTransformedLayer) {
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If a layer is transformed, the damage rect should still enclose the entire
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // transformed layer.
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithOneSurface();
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerImpl* child = root->children()[0];
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Transform rotation;
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  rotation.Rotate(45.0);
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
41646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  child->SetTransformOrigin(gfx::Point3F(
41746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      child->bounds().width() * 0.5f, child->bounds().height() * 0.5f, 0.f));
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  child->SetPosition(gfx::PointF(85.f, 85.f));
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Sanity check that the layer actually moved to (85, 85), damaging its old
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // location and new location.
423c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect root_damage_rect =
424c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      root->render_surface()->damage_tracker()->current_damage_rect();
425c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(85, 85, 45, 45).ToString(), root_damage_rect.ToString());
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // With the anchor on the layer's center, now we can test the rotation more
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // intuitively, since it applies about the layer's anchor.
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  child->SetTransform(rotation);
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Since the child layer is square, rotation by 45 degrees about the center
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // should increase the size of the expected rect by sqrt(2), centered around
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // (100, 100). The old exposed region should be fully contained in the new
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // region.
43758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  float expected_width = 30.f * sqrt(2.f);
43858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  float expected_position = 100.f - 0.5f * expected_width;
439c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect expected_rect = gfx::ToEnclosingRect(gfx::RectF(
440c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      expected_position, expected_position, expected_width, expected_width));
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root_damage_rect =
44258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      root->render_surface()->damage_tracker()->current_damage_rect();
443c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(expected_rect.ToString(), root_damage_rect.ToString());
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(DamageTrackerTest, VerifyDamageForPerspectiveClippedLayer) {
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If a layer has a perspective transform that causes w < 0, then not
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // clipping the layer can cause an invalid damage rect. This test checks that
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the w < 0 case is tracked properly.
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The transform is constructed so that if w < 0 clipping is not performed,
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the incorrect rect will be very small, specifically: position (500.972504,
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // 498.544617) and size 0.056610 x 2.910767.  Instead, the correctly
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // transformed rect should actually be very huge (i.e. in theory, -infinity
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // on the left), and positioned so that the right-most bound rect will be
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // approximately 501 units in root surface space.
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithOneSurface();
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerImpl* child = root->children()[0];
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Transform transform;
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  transform.Translate3d(500.0, 500.0, 0.0);
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  transform.ApplyPerspectiveDepth(1.0);
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  transform.RotateAboutYAxis(45.0);
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  transform.Translate3d(-50.0, -50.0, 0.0);
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Set up the child
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  child->SetPosition(gfx::PointF(0.f, 0.f));
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  child->SetBounds(gfx::Size(100, 100));
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  child->SetContentBounds(gfx::Size(100, 100));
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  child->SetTransform(transform);
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Sanity check that the child layer's bounds would actually get clipped by
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // w < 0, otherwise this test is not actually testing the intended scenario.
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::QuadF test_quad(gfx::RectF(gfx::PointF(), gfx::SizeF(100.f, 100.f)));
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool clipped = false;
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MathUtil::MapQuad(transform, test_quad, &clipped);
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(clipped);
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Damage the child without moving it.
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  child->SetOpacity(0.5f);
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The expected damage should cover the entire root surface (500x500), but we
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // don't care whether the damage rect was clamped or is larger than the
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // surface for this test.
490c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect root_damage_rect =
491c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      root->render_surface()->damage_tracker()->current_damage_rect();
492c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect damage_we_care_about = gfx::Rect(gfx::Size(500, 500));
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(root_damage_rect.Contains(damage_we_care_about));
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(DamageTrackerTest, VerifyDamageForBlurredSurface) {
497b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithTwoSurfaces();
498b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  LayerImpl* surface = root->children()[0];
499b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  LayerImpl* child = surface->children()[0];
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
501eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  FilterOperations filters;
502eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  filters.Append(FilterOperation::CreateBlurFilter(5.f));
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int outset_top, outset_right, outset_bottom, outset_left;
504eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  filters.GetOutsets(&outset_top, &outset_right, &outset_bottom, &outset_left);
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Setting the filter will damage the whole surface.
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
508b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  surface->SetFilters(filters);
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Setting the update rect should cause the corresponding damage to the
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // surface, blurred based on the size of the blur filter.
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
5145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  child->SetUpdateRect(gfx::RectF(1.f, 2.f, 3.f, 4.f));
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
517b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Damage position on the surface should be: position of update_rect (1, 2)
518b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // relative to the child (300, 300), but expanded by the blur outsets.
519c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect root_damage_rect =
520c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      root->render_surface()->damage_tracker()->current_damage_rect();
521c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect expected_damage_rect = gfx::Rect(301, 302, 3, 4);
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_damage_rect.Inset(-outset_left,
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             -outset_top,
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             -outset_right,
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             -outset_bottom);
527c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(expected_damage_rect.ToString(), root_damage_rect.ToString());
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(DamageTrackerTest, VerifyDamageForImageFilter) {
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithOneSurface();
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerImpl* child = root->children()[0];
533c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect root_damage_rect, child_damage_rect;
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Allow us to set damage on child too.
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  child->SetDrawsContent(true);
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
538cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  skia::RefPtr<SkImageFilter> filter = skia::AdoptRef(
539cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      SkBlurImageFilter::Create(SkIntToScalar(2), SkIntToScalar(2)));
54068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  FilterOperations filters;
54168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  filters.Append(FilterOperation::CreateReferenceFilter(filter));
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Setting the filter will damage the whole surface.
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
54568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  child->SetFilters(filters);
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root_damage_rect =
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          root->render_surface()->damage_tracker()->current_damage_rect();
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  child_damage_rect =
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          child->render_surface()->damage_tracker()->current_damage_rect();
551c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(100, 100, 30, 30).ToString(),
552c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            root_damage_rect.ToString());
553c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(30, 30).ToString(), child_damage_rect.ToString());
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // CASE 1: Setting the update rect should damage the whole surface (for now)
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
557c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  child->SetUpdateRect(gfx::RectF(1.f, 1.f));
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root_damage_rect =
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          root->render_surface()->damage_tracker()->current_damage_rect();
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  child_damage_rect =
5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          child->render_surface()->damage_tracker()->current_damage_rect();
564c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(100, 100, 30, 30).ToString(),
565c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            root_damage_rect.ToString());
566c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(30.f, 30.f).ToString(), child_damage_rect.ToString());
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(DamageTrackerTest, VerifyDamageForBackgroundBlurredChild) {
5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithTwoSurfaces();
5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerImpl* child1 = root->children()[0];
5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerImpl* child2 = root->children()[1];
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Allow us to set damage on child1 too.
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  child1->SetDrawsContent(true);
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
577eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  FilterOperations filters;
578eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  filters.Append(FilterOperation::CreateBlurFilter(2.f));
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int outset_top, outset_right, outset_bottom, outset_left;
580eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  filters.GetOutsets(&outset_top, &outset_right, &outset_bottom, &outset_left);
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Setting the filter will damage the whole surface.
5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  child1->SetBackgroundFilters(filters);
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // CASE 1: Setting the update rect should cause the corresponding damage to
5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //         the surface, blurred based on the size of the child's background
5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //         blur filter.
5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
5915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  root->SetUpdateRect(gfx::RectF(297.f, 297.f, 2.f, 2.f));
5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
594c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect root_damage_rect =
595c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      root->render_surface()->damage_tracker()->current_damage_rect();
5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Damage position on the surface should be a composition of the damage on
5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the root and on child2.  Damage on the root should be: position of
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // update_rect (297, 297), but expanded by the blur outsets.
599c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect expected_damage_rect = gfx::Rect(297, 297, 2, 2);
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_damage_rect.Inset(-outset_left,
6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             -outset_top,
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             -outset_right,
6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             -outset_bottom);
605c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(expected_damage_rect.ToString(), root_damage_rect.ToString());
6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // CASE 2: Setting the update rect should cause the corresponding damage to
6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //         the surface, blurred based on the size of the child's background
6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //         blur filter. Since the damage extends to the right/bottom outside
6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //         of the blurred layer, only the left/top should end up expanded.
6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
6125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  root->SetUpdateRect(gfx::RectF(297.f, 297.f, 30.f, 30.f));
6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root_damage_rect =
6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          root->render_surface()->damage_tracker()->current_damage_rect();
6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Damage position on the surface should be a composition of the damage on
6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the root and on child2.  Damage on the root should be: position of
6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // update_rect (297, 297), but expanded on the left/top by the blur outsets.
620c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  expected_damage_rect = gfx::Rect(297, 297, 30, 30);
6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_damage_rect.Inset(-outset_left,
6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             -outset_top,
6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             0,
6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             0);
626c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(expected_damage_rect.ToString(), root_damage_rect.ToString());
6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // CASE 3: Setting this update rect outside the blurred content_bounds of the
6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //         blurred child1 will not cause it to be expanded.
6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
6315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  root->SetUpdateRect(gfx::RectF(30.f, 30.f, 2.f, 2.f));
6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root_damage_rect =
6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          root->render_surface()->damage_tracker()->current_damage_rect();
6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Damage on the root should be: position of update_rect (30, 30), not
6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // expanded.
638c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  expected_damage_rect = gfx::Rect(30, 30, 2, 2);
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
640c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(expected_damage_rect.ToString(), root_damage_rect.ToString());
6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // CASE 4: Setting this update rect inside the blurred content_bounds but
6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //         outside the original content_bounds of the blurred child1 will
6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //         cause it to be expanded.
6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
6465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  root->SetUpdateRect(gfx::RectF(99.f, 99.f, 1.f, 1.f));
6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root_damage_rect =
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          root->render_surface()->damage_tracker()->current_damage_rect();
6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Damage on the root should be: position of update_rect (99, 99), expanded by
6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the blurring on child1, but since it is 1 pixel outside the layer, the
6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // expanding should be reduced by 1.
654c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  expected_damage_rect = gfx::Rect(99, 99, 1, 1);
6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_damage_rect.Inset(-outset_left + 1,
6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             -outset_top + 1,
6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             -outset_right,
6592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             -outset_bottom);
660c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(expected_damage_rect.ToString(), root_damage_rect.ToString());
6612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // CASE 5: Setting the update rect on child2, which is above child1, will
6632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // not get blurred by child1, so it does not need to get expanded.
6642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
6655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  child2->SetUpdateRect(gfx::RectF(0.f, 0.f, 1.f, 1.f));
6662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root_damage_rect =
6692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          root->render_surface()->damage_tracker()->current_damage_rect();
6702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Damage on child2 should be: position of update_rect offset by the child's
6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // position (11, 11), and not expanded by anything.
672c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  expected_damage_rect = gfx::Rect(11, 11, 1, 1);
6732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
674c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(expected_damage_rect.ToString(), root_damage_rect.ToString());
6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // CASE 6: Setting the update rect on child1 will also blur the damage, so
6772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //         that any pixels needed for the blur are redrawn in the current
6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //         frame.
6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
6805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  child1->SetUpdateRect(gfx::RectF(0.f, 0.f, 1.f, 1.f));
6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
6822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root_damage_rect =
6842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          root->render_surface()->damage_tracker()->current_damage_rect();
6852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Damage on child1 should be: position of update_rect offset by the child's
6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // position (100, 100), and expanded by the damage.
687c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  expected_damage_rect = gfx::Rect(100, 100, 1, 1);
6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_damage_rect.Inset(-outset_left,
6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             -outset_top,
6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             -outset_right,
6922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             -outset_bottom);
693c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(expected_damage_rect.ToString(), root_damage_rect.ToString());
6942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(DamageTrackerTest, VerifyDamageForAddingAndRemovingLayer) {
6972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithOneSurface();
6982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerImpl* child1 = root->children()[0];
6992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // CASE 1: Adding a new layer should cause the appropriate damage.
7012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
7022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
7032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
7042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<LayerImpl> child2 =
7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            LayerImpl::Create(host_impl_.active_tree(), 3);
7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    child2->SetPosition(gfx::PointF(400.f, 380.f));
7072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    child2->SetBounds(gfx::Size(6, 8));
7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    child2->SetContentBounds(gfx::Size(6, 8));
7092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    child2->SetDrawsContent(true);
7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    root->AddChild(child2.Pass());
7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Sanity check - all 3 layers should be on the same render surface; render
7152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // surfaces are tested elsewhere.
7162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(3u, root->render_surface()->layer_list().size());
7172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
718c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect root_damage_rect =
719c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      root->render_surface()->damage_tracker()->current_damage_rect();
720c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(400, 380, 6, 8).ToString(), root_damage_rect.ToString());
7212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // CASE 2: If the layer is removed, its entire old layer becomes exposed, not
7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //         just the last update rect.
7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Advance one frame without damage so that we know the damage rect is not
7262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // leftover from the previous case.
7272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root_damage_rect =
7312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          root->render_surface()->damage_tracker()->current_damage_rect();
7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(root_damage_rect.IsEmpty());
7332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Then, test removing child1.
7352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root->RemoveChild(child1);
7362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  child1 = NULL;
7372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
7382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root_damage_rect =
7402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          root->render_surface()->damage_tracker()->current_damage_rect();
741c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(100, 100, 30, 30).ToString(),
742c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            root_damage_rect.ToString());
7432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(DamageTrackerTest, VerifyDamageForNewUnchangedLayer) {
7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If child2 is added to the layer tree, but it doesn't have any explicit
7472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // damage of its own, it should still indeed damage the target surface.
7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithOneSurface();
7502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
7522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
7532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<LayerImpl> child2 =
7542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            LayerImpl::Create(host_impl_.active_tree(), 3);
7552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    child2->SetPosition(gfx::PointF(400.f, 380.f));
7562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    child2->SetBounds(gfx::Size(6, 8));
7572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    child2->SetContentBounds(gfx::Size(6, 8));
7582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    child2->SetDrawsContent(true);
7592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    child2->ResetAllChangeTrackingForSubtree();
7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Sanity check the initial conditions of the test, if these asserts
7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // trigger, it means the test no longer actually covers the intended
7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // scenario.
7632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ASSERT_FALSE(child2->LayerPropertyChanged());
7642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ASSERT_TRUE(child2->update_rect().IsEmpty());
7652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    root->AddChild(child2.Pass());
7662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
7682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Sanity check - all 3 layers should be on the same render surface; render
7702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // surfaces are tested elsewhere.
7712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(3u, root->render_surface()->layer_list().size());
7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
773c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect root_damage_rect =
774c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      root->render_surface()->damage_tracker()->current_damage_rect();
775c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(400, 380, 6, 8).ToString(), root_damage_rect.ToString());
7762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(DamageTrackerTest, VerifyDamageForMultipleLayers) {
7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithOneSurface();
7802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerImpl* child1 = root->children()[0];
7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // In this test we don't want the above tree manipulation to be considered
7832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // part of the same frame.
7842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<LayerImpl> child2 =
7872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            LayerImpl::Create(host_impl_.active_tree(), 3);
7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    child2->SetPosition(gfx::PointF(400.f, 380.f));
7892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    child2->SetBounds(gfx::Size(6, 8));
7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    child2->SetContentBounds(gfx::Size(6, 8));
7912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    child2->SetDrawsContent(true);
7922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    root->AddChild(child2.Pass());
7932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerImpl* child2 = root->children()[1];
7952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
7962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Damaging two layers simultaneously should cause combined damage.
798c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // - child1 update rect in surface space: gfx::Rect(100, 100, 1, 2);
799c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // - child2 update rect in surface space: gfx::Rect(400, 380, 3, 4);
8002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
8015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  child1->SetUpdateRect(gfx::RectF(0.f, 0.f, 1.f, 2.f));
8025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  child2->SetUpdateRect(gfx::RectF(0.f, 0.f, 3.f, 4.f));
8032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
804c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect root_damage_rect =
805c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      root->render_surface()->damage_tracker()->current_damage_rect();
806c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(100, 100, 303, 284).ToString(),
807c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            root_damage_rect.ToString());
8082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(DamageTrackerTest, VerifyDamageForNestedSurfaces) {
8112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithTwoSurfaces();
8122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerImpl* child1 = root->children()[0];
8132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerImpl* child2 = root->children()[1];
8142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerImpl* grand_child1 = root->children()[0]->children()[0];
815c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect child_damage_rect;
816c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect root_damage_rect;
8172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // CASE 1: Damage to a descendant surface should propagate properly to
8192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //         ancestor surface.
8202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
8212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  grand_child1->SetOpacity(0.5f);
8222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
8232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  child_damage_rect =
8242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          child1->render_surface()->damage_tracker()->current_damage_rect();
8252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root_damage_rect =
8262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          root->render_surface()->damage_tracker()->current_damage_rect();
827c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(200, 200, 6, 8).ToString(), child_damage_rect.ToString());
828c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(300, 300, 6, 8).ToString(), root_damage_rect.ToString());
8292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // CASE 2: Same as previous case, but with additional damage elsewhere that
8312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //         should be properly unioned.
8322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // - child1 surface damage in root surface space:
833c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  //   gfx::Rect(300, 300, 6, 8);
8342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // - child2 damage in root surface space:
835c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  //   gfx::Rect(11, 11, 18, 18);
8362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
8372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  grand_child1->SetOpacity(0.7f);
8382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  child2->SetOpacity(0.7f);
8392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
8402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  child_damage_rect =
8412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          child1->render_surface()->damage_tracker()->current_damage_rect();
8422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root_damage_rect =
8432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          root->render_surface()->damage_tracker()->current_damage_rect();
844c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(200, 200, 6, 8).ToString(), child_damage_rect.ToString());
845c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(11, 11, 295, 297).ToString(),
846c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            root_damage_rect.ToString());
8472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(DamageTrackerTest, VerifyDamageForSurfaceChangeFromDescendantLayer) {
8502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If descendant layer changes and affects the content bounds of the render
8512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // surface, then the entire descendant surface should be damaged, and it
8522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // should damage its ancestor surface with the old and new surface regions.
8532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This is a tricky case, since only the first grand_child changes, but the
8552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // entire surface should be marked dirty.
8562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithTwoSurfaces();
8582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerImpl* child1 = root->children()[0];
8592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerImpl* grand_child1 = root->children()[0]->children()[0];
860c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect child_damage_rect;
861c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect root_damage_rect;
8622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
8642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  grand_child1->SetPosition(gfx::PointF(195.f, 205.f));
8652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
8662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  child_damage_rect =
8672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          child1->render_surface()->damage_tracker()->current_damage_rect();
8682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root_damage_rect =
8692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          root->render_surface()->damage_tracker()->current_damage_rect();
8702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The new surface bounds should be damaged entirely, even though only one of
8722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the layers changed.
873c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(190, 190, 11, 23).ToString(),
874c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            child_damage_rect.ToString());
8752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Damage to the root surface should be the union of child1's *entire* render
8772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // surface (in target space), and its old exposed area (also in target
8782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // space).
879c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(290, 290, 16, 23).ToString(),
880c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            root_damage_rect.ToString());
8812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(DamageTrackerTest, VerifyDamageForSurfaceChangeFromAncestorLayer) {
8842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // An ancestor/owning layer changes that affects the position/transform of
8852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the render surface. Note that in this case, the layer_property_changed flag
8862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // already propagates to the subtree (tested in LayerImpltest), which damages
8872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the entire child1 surface, but the damage tracker still needs the correct
8882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // logic to compute the exposed region on the root surface.
8892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
890eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // TODO(shawnsingh): the expectations of this test case should change when we
891eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // add support for a unique scissor_rect per RenderSurface. In that case, the
892eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // child1 surface should be completely unchanged, since we are only
893eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // transforming it, while the root surface would be damaged appropriately.
8942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithTwoSurfaces();
8962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerImpl* child1 = root->children()[0];
897c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect child_damage_rect;
898c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect root_damage_rect;
8992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
9012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  child1->SetPosition(gfx::PointF(50.f, 50.f));
9022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
9032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  child_damage_rect =
9042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          child1->render_surface()->damage_tracker()->current_damage_rect();
9052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root_damage_rect =
9062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          root->render_surface()->damage_tracker()->current_damage_rect();
9072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The new surface bounds should be damaged entirely.
909c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(190, 190, 16, 18).ToString(),
910c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            child_damage_rect.ToString());
9112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The entire child1 surface and the old exposed child1 surface should damage
9132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the root surface.
914c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  //  - old child1 surface in target space: gfx::Rect(290, 290, 16, 18)
915c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  //  - new child1 surface in target space: gfx::Rect(240, 240, 16, 18)
916c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(240, 240, 66, 68).ToString(),
917c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            root_damage_rect.ToString());
9182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(DamageTrackerTest, VerifyDamageForAddingAndRemovingRenderSurfaces) {
9212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithTwoSurfaces();
9222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerImpl* child1 = root->children()[0];
923c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect child_damage_rect;
924c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect root_damage_rect;
9252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // CASE 1: If a descendant surface disappears, its entire old area becomes
9272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //         exposed.
9282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
9292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  child1->SetOpacity(1.f);
9302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  child1->SetForceRenderSurface(false);
9312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
9322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Sanity check that there is only one surface now.
9342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_FALSE(child1->render_surface());
9352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(4u, root->render_surface()->layer_list().size());
9362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root_damage_rect =
9382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          root->render_surface()->damage_tracker()->current_damage_rect();
939c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(290, 290, 16, 18).ToString(),
940c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            root_damage_rect.ToString());
9412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // CASE 2: If a descendant surface appears, its entire old area becomes
9432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //         exposed.
9442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Cycle one frame of no change, just to sanity check that the next rect is
9462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // not because of the old damage state.
9472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
9482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
9492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root_damage_rect =
9502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          root->render_surface()->damage_tracker()->current_damage_rect();
9512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(root_damage_rect.IsEmpty());
9522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Then change the tree so that the render surface is added back.
9542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
9552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  child1->SetOpacity(0.5f);
9562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  child1->SetForceRenderSurface(true);
9572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
9582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Sanity check that there is a new surface now.
9602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(child1->render_surface());
9612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(3u, root->render_surface()->layer_list().size());
9622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(2u, child1->render_surface()->layer_list().size());
9632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  child_damage_rect =
9652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          child1->render_surface()->damage_tracker()->current_damage_rect();
9662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root_damage_rect =
9672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          root->render_surface()->damage_tracker()->current_damage_rect();
968c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(190, 190, 16, 18).ToString(),
969c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            child_damage_rect.ToString());
970c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(290, 290, 16, 18).ToString(),
971c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            root_damage_rect.ToString());
9722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(DamageTrackerTest, VerifyNoDamageWhenNothingChanged) {
9752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithTwoSurfaces();
9762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerImpl* child1 = root->children()[0];
977c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect child_damage_rect;
978c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect root_damage_rect;
9792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // CASE 1: If nothing changes, the damage rect should be empty.
9812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
9822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
9832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
9842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  child_damage_rect =
9852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          child1->render_surface()->damage_tracker()->current_damage_rect();
9862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root_damage_rect =
9872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          root->render_surface()->damage_tracker()->current_damage_rect();
9882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(child_damage_rect.IsEmpty());
9892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(root_damage_rect.IsEmpty());
9902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // CASE 2: If nothing changes twice in a row, the damage rect should still be
9922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //         empty.
9932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
9942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
9952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
9962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  child_damage_rect =
9972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          child1->render_surface()->damage_tracker()->current_damage_rect();
9982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root_damage_rect =
9992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          root->render_surface()->damage_tracker()->current_damage_rect();
10002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(child_damage_rect.IsEmpty());
10012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(root_damage_rect.IsEmpty());
10022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(DamageTrackerTest, VerifyNoDamageForUpdateRectThatDoesNotDrawContent) {
10052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithTwoSurfaces();
10062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerImpl* child1 = root->children()[0];
1007c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect child_damage_rect;
1008c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect root_damage_rect;
10092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // In our specific tree, the update rect of child1 should not cause any
10112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // damage to any surface because it does not actually draw content.
10122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
10135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  child1->SetUpdateRect(gfx::RectF(0.f, 0.f, 1.f, 2.f));
10142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
10152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  child_damage_rect =
10162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          child1->render_surface()->damage_tracker()->current_damage_rect();
10172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root_damage_rect =
10182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          root->render_surface()->damage_tracker()->current_damage_rect();
10192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(child_damage_rect.IsEmpty());
10202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(root_damage_rect.IsEmpty());
10212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(DamageTrackerTest, VerifyDamageForReplica) {
10242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithTwoSurfaces();
10252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerImpl* child1 = root->children()[0];
10262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerImpl* grand_child1 = child1->children()[0];
10272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerImpl* grand_child2 = child1->children()[1];
10282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Damage on a surface that has a reflection should cause the target surface
10302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // to receive the surface's damage and the surface's reflected damage.
10312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // For this test case, we modify grand_child2, and add grand_child3 to extend
10332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the bounds of child1's surface. This way, we can test reflection changes
10342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // without changing content_bounds of the surface.
10352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  grand_child2->SetPosition(gfx::PointF(180.f, 180.f));
10362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
10372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<LayerImpl> grand_child3 =
10382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            LayerImpl::Create(host_impl_.active_tree(), 6);
10392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    grand_child3->SetPosition(gfx::PointF(240.f, 240.f));
10402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    grand_child3->SetBounds(gfx::Size(10, 10));
10412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    grand_child3->SetContentBounds(gfx::Size(10, 10));
10422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    grand_child3->SetDrawsContent(true);
10432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    child1->AddChild(grand_child3.Pass());
10442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
10452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  child1->SetOpacity(0.5f);
10462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
10472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // CASE 1: adding a reflection about the left edge of grand_child1.
10492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
10502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
10512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
10522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<LayerImpl> grand_child1_replica =
10532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            LayerImpl::Create(host_impl_.active_tree(), 7);
10542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    grand_child1_replica->SetPosition(gfx::PointF());
10552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gfx::Transform reflection;
10562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    reflection.Scale3d(-1.0, 1.0, 1.0);
10572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    grand_child1_replica->SetTransform(reflection);
10582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    grand_child1->SetReplicaLayer(grand_child1_replica.Pass());
10592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
10602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
10612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1062c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect grand_child_damage_rect =
1063c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      grand_child1->render_surface()->damage_tracker()->current_damage_rect();
1064c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect child_damage_rect =
1065c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      child1->render_surface()->damage_tracker()->current_damage_rect();
1066c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect root_damage_rect =
1067c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      root->render_surface()->damage_tracker()->current_damage_rect();
10682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The grand_child surface damage should not include its own replica. The
10702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // child surface damage should include the normal and replica surfaces.
1071c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(6, 8).ToString(), grand_child_damage_rect.ToString());
1072c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(194, 200, 12, 8).ToString(),
1073c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            child_damage_rect.ToString());
1074c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(294, 300, 12, 8).ToString(), root_damage_rect.ToString());
10752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // CASE 2: moving the descendant surface should cause both the original and
10772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //         reflected areas to be damaged on the target.
10782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
10792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect old_content_rect = child1->render_surface()->content_rect();
10802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  grand_child1->SetPosition(gfx::PointF(195.f, 205.f));
10812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
10822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(old_content_rect.width(),
10832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            child1->render_surface()->content_rect().width());
10842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(old_content_rect.height(),
10852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            child1->render_surface()->content_rect().height());
10862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  grand_child_damage_rect =
10882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          grand_child1->render_surface()->
10892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              damage_tracker()->current_damage_rect();
10902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  child_damage_rect =
10912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          child1->render_surface()->damage_tracker()->current_damage_rect();
10922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root_damage_rect =
10932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          root->render_surface()->damage_tracker()->current_damage_rect();
10942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The child surface damage should include normal and replica surfaces for
10962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // both old and new locations.
1097c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  //  - old location in target space: gfx::Rect(194, 200, 12, 8)
1098c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  //  - new location in target space: gfx::Rect(189, 205, 12, 8)
1099c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(6, 8).ToString(), grand_child_damage_rect.ToString());
1100c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(189, 200, 17, 13).ToString(),
1101c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            child_damage_rect.ToString());
1102c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(289, 300, 17, 13).ToString(),
1103c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            root_damage_rect.ToString());
11042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // CASE 3: removing the reflection should cause the entire region including
11062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //         reflection to damage the target surface.
11072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
11082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  grand_child1->SetReplicaLayer(scoped_ptr<LayerImpl>());
11092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
11102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(old_content_rect.width(),
11112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            child1->render_surface()->content_rect().width());
11122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(old_content_rect.height(),
11132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            child1->render_surface()->content_rect().height());
11142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(grand_child1->render_surface());
11162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  child_damage_rect =
11172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          child1->render_surface()->damage_tracker()->current_damage_rect();
11182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root_damage_rect =
11192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          root->render_surface()->damage_tracker()->current_damage_rect();
11202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1121c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(189, 205, 12, 8).ToString(),
1122c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            child_damage_rect.ToString());
1123c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(289, 305, 12, 8).ToString(), root_damage_rect.ToString());
11242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
11252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(DamageTrackerTest, VerifyDamageForMask) {
11272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithOneSurface();
11282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerImpl* child = root->children()[0];
11292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // In the current implementation of the damage tracker, changes to mask
11312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // layers should damage the entire corresponding surface.
11322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
11342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Set up the mask layer.
11362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
11372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<LayerImpl> mask_layer =
11382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            LayerImpl::Create(host_impl_.active_tree(), 3);
11392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    mask_layer->SetPosition(child->position());
11402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    mask_layer->SetBounds(child->bounds());
11412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    mask_layer->SetContentBounds(child->bounds());
11422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    child->SetMaskLayer(mask_layer.Pass());
11432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
11442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerImpl* mask_layer = child->mask_layer();
11452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Add opacity and a grand_child so that the render surface persists even
11472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // after we remove the mask.
11482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  child->SetOpacity(0.5f);
11492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
11502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<LayerImpl> grand_child =
11512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            LayerImpl::Create(host_impl_.active_tree(), 4);
11522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    grand_child->SetPosition(gfx::PointF(2.f, 2.f));
11532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    grand_child->SetBounds(gfx::Size(2, 2));
11542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    grand_child->SetContentBounds(gfx::Size(2, 2));
11552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    grand_child->SetDrawsContent(true);
11562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    child->AddChild(grand_child.Pass());
11572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
11582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
11592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Sanity check that a new surface was created for the child.
11612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(child->render_surface());
11622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // CASE 1: the update_rect on a mask layer should damage the entire target
11642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //         surface.
11652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
11665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  mask_layer->SetUpdateRect(gfx::RectF(1.f, 2.f, 3.f, 4.f));
11672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
1168c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect child_damage_rect =
1169c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      child->render_surface()->damage_tracker()->current_damage_rect();
1170c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(30, 30).ToString(), child_damage_rect.ToString());
11712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // CASE 2: a property change on the mask layer should damage the entire
11732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //         target surface.
11742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Advance one frame without damage so that we know the damage rect is not
11762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // leftover from the previous case.
11772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
11782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
11792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  child_damage_rect =
11802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          child->render_surface()->damage_tracker()->current_damage_rect();
11812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(child_damage_rect.IsEmpty());
11822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Then test the property change.
11842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
11852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  mask_layer->SetStackingOrderChanged(true);
11862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
11882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  child_damage_rect =
11892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          child->render_surface()->damage_tracker()->current_damage_rect();
1190c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(30, 30).ToString(), child_damage_rect.ToString());
11912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // CASE 3: removing the mask also damages the entire target surface.
11932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
11942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Advance one frame without damage so that we know the damage rect is not
11962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // leftover from the previous case.
11972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
11982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
11992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  child_damage_rect =
12002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          child->render_surface()->damage_tracker()->current_damage_rect();
12012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(child_damage_rect.IsEmpty());
12022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Then test mask removal.
12042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
12052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  child->SetMaskLayer(scoped_ptr<LayerImpl>());
12062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(child->LayerPropertyChanged());
12072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
12082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Sanity check that a render surface still exists.
12102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(child->render_surface());
12112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  child_damage_rect =
12132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          child->render_surface()->damage_tracker()->current_damage_rect();
1214c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(30, 30).ToString(), child_damage_rect.ToString());
12152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
12162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(DamageTrackerTest, VerifyDamageForReplicaMask) {
12182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithTwoSurfaces();
12192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerImpl* child1 = root->children()[0];
12202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerImpl* grand_child1 = child1->children()[0];
12212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Changes to a replica's mask should not damage the original surface,
12232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // because it is not masked. But it does damage the ancestor target surface.
12242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
12262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Create a reflection about the left edge of grand_child1.
12282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
12292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<LayerImpl> grand_child1_replica =
12302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            LayerImpl::Create(host_impl_.active_tree(), 6);
12312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    grand_child1_replica->SetPosition(gfx::PointF());
12322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gfx::Transform reflection;
12332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    reflection.Scale3d(-1.0, 1.0, 1.0);
12342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    grand_child1_replica->SetTransform(reflection);
12352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    grand_child1->SetReplicaLayer(grand_child1_replica.Pass());
12362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
12372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerImpl* grand_child1_replica = grand_child1->replica_layer();
12382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Set up the mask layer on the replica layer
12402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
12412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<LayerImpl> replica_mask_layer =
12422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            LayerImpl::Create(host_impl_.active_tree(), 7);
12432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    replica_mask_layer->SetPosition(gfx::PointF());
12442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    replica_mask_layer->SetBounds(grand_child1->bounds());
12452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    replica_mask_layer->SetContentBounds(grand_child1->bounds());
12462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    grand_child1_replica->SetMaskLayer(replica_mask_layer.Pass());
12472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
12482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerImpl* replica_mask_layer = grand_child1_replica->mask_layer();
12492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
12512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Sanity check that the appropriate render surfaces were created
12532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(grand_child1->render_surface());
12542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // CASE 1: a property change on the mask should damage only the reflected
12562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //         region on the target surface.
12572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
12582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  replica_mask_layer->SetStackingOrderChanged(true);
12592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
12602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1261c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect grand_child_damage_rect =
1262c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      grand_child1->render_surface()->damage_tracker()->current_damage_rect();
1263c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect child_damage_rect =
1264c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      child1->render_surface()->damage_tracker()->current_damage_rect();
12652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(grand_child_damage_rect.IsEmpty());
1267c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(194, 200, 6, 8).ToString(), child_damage_rect.ToString());
12682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // CASE 2: removing the replica mask damages only the reflected region on the
12702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //         target surface.
12712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
12722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
12732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  grand_child1_replica->SetMaskLayer(scoped_ptr<LayerImpl>());
12742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
12752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  grand_child_damage_rect =
12772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          grand_child1->render_surface()->damage_tracker()->
12782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              current_damage_rect();
12792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  child_damage_rect =
12802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          child1->render_surface()->damage_tracker()->current_damage_rect();
12812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(grand_child_damage_rect.IsEmpty());
1283c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(194, 200, 6, 8).ToString(), child_damage_rect.ToString());
12842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
12852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
128646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)TEST_F(DamageTrackerTest, VerifyDamageForReplicaMaskWithTransformOrigin) {
12872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithTwoSurfaces();
12882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerImpl* child1 = root->children()[0];
12892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerImpl* grand_child1 = child1->children()[0];
12902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Verify that the correct replica_origin_transform is used for the
12922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // replica_mask.
12932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
12942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
129546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // This is not actually the transform origin point being tested, but by
129646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // convention its
12972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // expected to be the same as the replica's anchor point.
129846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  grand_child1->SetTransformOrigin(
129946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      gfx::Point3F(grand_child1->bounds().width(), 0.f, 0.f));
13002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
13022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<LayerImpl> grand_child1_replica =
13032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            LayerImpl::Create(host_impl_.active_tree(), 6);
13042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    grand_child1_replica->SetPosition(gfx::PointF());
13052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // This is the anchor being tested.
130746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    grand_child1_replica->SetTransformOrigin(
130846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        gfx::Point3F(grand_child1->bounds().width(), 0.f, 0.f));
13092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gfx::Transform reflection;
13102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    reflection.Scale3d(-1.0, 1.0, 1.0);
13112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    grand_child1_replica->SetTransform(reflection);
13122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    grand_child1->SetReplicaLayer(grand_child1_replica.Pass());
13132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
13142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerImpl* grand_child1_replica = grand_child1->replica_layer();
13152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Set up the mask layer on the replica layer
13172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
13182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<LayerImpl> replica_mask_layer =
13192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            LayerImpl::Create(host_impl_.active_tree(), 7);
13202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    replica_mask_layer->SetPosition(gfx::PointF());
132146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // Note: this is not the transform origin being tested.
13222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    replica_mask_layer->SetBounds(grand_child1->bounds());
13232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    replica_mask_layer->SetContentBounds(grand_child1->bounds());
13242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    grand_child1_replica->SetMaskLayer(replica_mask_layer.Pass());
13252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
13262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerImpl* replica_mask_layer = grand_child1_replica->mask_layer();
13272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
13292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Sanity check that the appropriate render surfaces were created
13312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(grand_child1->render_surface());
13322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // A property change on the replica_mask should damage the reflected region on
13342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the target surface.
13352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
13362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  replica_mask_layer->SetStackingOrderChanged(true);
13372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
13392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1340c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect child_damage_rect =
1341c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      child1->render_surface()->damage_tracker()->current_damage_rect();
1342c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(206, 200, 6, 8).ToString(), child_damage_rect.ToString());
13432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
13442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(DamageTrackerTest, DamageWhenAddedExternally) {
13462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithOneSurface();
13472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerImpl* child = root->children()[0];
13482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 1: This test ensures that when the tracker is given damage, that
1350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  //         it is included with any other partial damage.
13512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
13522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
13535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  child->SetUpdateRect(gfx::RectF(10, 11, 12, 13));
1354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  root->render_surface()->damage_tracker()->AddDamageNextUpdate(
1355c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      gfx::Rect(15, 16, 32, 33));
13562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
1357c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect root_damage_rect =
1358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      root->render_surface()->damage_tracker()->current_damage_rect();
1359c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::UnionRects(gfx::Rect(15, 16, 32, 33),
1360c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                            gfx::Rect(100 + 10, 100 + 11, 12, 13)).ToString(),
1361c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            root_damage_rect.ToString());
13622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 2: An additional sanity check that adding damage works even when
1364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  //         nothing on the layer tree changed.
13652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
13662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
1367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  root->render_surface()->damage_tracker()->AddDamageNextUpdate(
1368c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      gfx::Rect(30, 31, 14, 15));
13692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
13702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root_damage_rect =
1371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      root->render_surface()->damage_tracker()->current_damage_rect();
1372c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(30, 31, 14, 15).ToString(), root_damage_rect.ToString());
13732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
13742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(DamageTrackerTest, VerifyDamageForEmptyLayerList) {
13762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Though it should never happen, its a good idea to verify that the damage
13772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // tracker does not crash when it receives an empty layer_list.
13782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_.active_tree(), 1);
13802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root->CreateRenderSurface();
13812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(root == root->render_target());
13832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RenderSurfaceImpl* target_surface = root->render_surface();
1384ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1385ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  LayerImplList empty_list;
13862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  target_surface->damage_tracker()->UpdateDamageTrackingState(
1387ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      empty_list,
13882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      target_surface->OwningLayerId(),
13892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      false,
13902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gfx::Rect(),
13912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      NULL,
139268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      FilterOperations());
13932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1394c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect damage_rect =
1395c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      target_surface->damage_tracker()->current_damage_rect();
13962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(damage_rect.IsEmpty());
13972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
13982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(DamageTrackerTest, VerifyDamageAccumulatesUntilReset) {
14002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If damage is not cleared, it should accumulate.
14012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithOneSurface();
14032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerImpl* child = root->children()[0];
14042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClearDamageForAllSurfaces(root.get());
1406c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  child->SetUpdateRect(gfx::Rect(10.f, 11.f, 1.f, 2.f));
14072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
14082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Sanity check damage after the first frame; this isnt the actual test yet.
1410c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect root_damage_rect =
1411c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      root->render_surface()->damage_tracker()->current_damage_rect();
1412c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(110, 111, 1, 2).ToString(), root_damage_rect.ToString());
14132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // New damage, without having cleared the previous damage, should be unioned
14152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // to the previous one.
14165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  child->SetUpdateRect(gfx::RectF(20.f, 25.f, 1.f, 2.f));
14172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
14182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root_damage_rect =
14192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          root->render_surface()->damage_tracker()->current_damage_rect();
1420c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(gfx::Rect(110, 111, 11, 16).ToString(),
1421c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            root_damage_rect.ToString());
14222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If we notify the damage tracker that we drew the damaged area, then damage
14242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // should be emptied.
14252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root->render_surface()->damage_tracker()->DidDrawDamagedArea();
14262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root_damage_rect =
14272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          root->render_surface()->damage_tracker()->current_damage_rect();
14282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(root_damage_rect.IsEmpty());
14292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Damage should remain empty even after one frame, since there's yet no new
14312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // damage.
14322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EmulateDrawingOneFrame(root.get());
14332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  root_damage_rect =
14342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          root->render_surface()->damage_tracker()->current_damage_rect();
14352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(root_damage_rect.IsEmpty());
14362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
14372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1438c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochTEST_F(DamageTrackerTest, HugeDamageRect) {
1439c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // This number is so large that we start losting floating point accuracy.
1440c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const int kBigNumber = 900000000;
1441c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Walk over a range to find floating point inaccuracy boundaries that move
1442c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // toward the wrong direction.
1443c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const int kRange = 5000;
1444c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1445c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  for (int i = 0; i < kRange; ++i) {
1446c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    scoped_ptr<LayerImpl> root = CreateTestTreeWithOneSurface();
1447c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    LayerImpl* child = root->children()[0];
1448c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1449c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    gfx::Transform transform;
1450c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    transform.Translate(-kBigNumber, -kBigNumber);
1451c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1452c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // The child layer covers (0, 0, i, i) of the viewport,
1453c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // but has a huge negative position.
1454c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    child->SetPosition(gfx::PointF());
1455c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    child->SetBounds(gfx::Size(kBigNumber + i, kBigNumber + i));
1456c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    child->SetContentBounds(gfx::Size(kBigNumber + i, kBigNumber + i));
1457c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    child->SetTransform(transform);
1458c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    EmulateDrawingOneFrame(root.get());
1459c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1460c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // The expected damage should cover the visible part of the child layer,
1461c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // which is (0, 0, i, i) in the viewport.
1462c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    gfx::Rect root_damage_rect =
1463c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        root->render_surface()->damage_tracker()->current_damage_rect();
1464c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    gfx::Rect damage_we_care_about = gfx::Rect(i, i);
1465c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    EXPECT_LE(damage_we_care_about.right(), root_damage_rect.right());
1466c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    EXPECT_LE(damage_we_care_about.bottom(), root_damage_rect.bottom());
1467c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
1468c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
1469c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
14702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
14712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace cc
1472