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