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