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