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