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