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