1 // Copyright 2012 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/occlusion_tracker.h" 6 7 #include "cc/animation/layer_animation_controller.h" 8 #include "cc/base/math_util.h" 9 #include "cc/debug/overdraw_metrics.h" 10 #include "cc/layers/layer.h" 11 #include "cc/layers/layer_impl.h" 12 #include "cc/output/copy_output_request.h" 13 #include "cc/output/copy_output_result.h" 14 #include "cc/output/filter_operation.h" 15 #include "cc/output/filter_operations.h" 16 #include "cc/test/animation_test_common.h" 17 #include "cc/test/fake_impl_proxy.h" 18 #include "cc/test/fake_layer_tree_host.h" 19 #include "cc/test/fake_layer_tree_host_impl.h" 20 #include "cc/test/geometry_test_utils.h" 21 #include "cc/test/occlusion_tracker_test_common.h" 22 #include "cc/trees/layer_tree_host_common.h" 23 #include "cc/trees/single_thread_proxy.h" 24 #include "testing/gmock/include/gmock/gmock.h" 25 #include "testing/gtest/include/gtest/gtest.h" 26 #include "ui/gfx/transform.h" 27 28 namespace cc { 29 namespace { 30 31 class TestContentLayer : public Layer { 32 public: 33 TestContentLayer() : Layer(), override_opaque_contents_rect_(false) { 34 SetIsDrawable(true); 35 } 36 37 virtual Region VisibleContentOpaqueRegion() const OVERRIDE { 38 if (override_opaque_contents_rect_) 39 return gfx::IntersectRects(opaque_contents_rect_, visible_content_rect()); 40 return Layer::VisibleContentOpaqueRegion(); 41 } 42 void SetOpaqueContentsRect(gfx::Rect opaque_contents_rect) { 43 override_opaque_contents_rect_ = true; 44 opaque_contents_rect_ = opaque_contents_rect; 45 } 46 47 private: 48 virtual ~TestContentLayer() {} 49 50 bool override_opaque_contents_rect_; 51 gfx::Rect opaque_contents_rect_; 52 }; 53 54 class TestContentLayerImpl : public LayerImpl { 55 public: 56 TestContentLayerImpl(LayerTreeImpl* tree_impl, int id) 57 : LayerImpl(tree_impl, id), override_opaque_contents_rect_(false) { 58 SetDrawsContent(true); 59 } 60 61 virtual Region VisibleContentOpaqueRegion() const OVERRIDE { 62 if (override_opaque_contents_rect_) 63 return gfx::IntersectRects(opaque_contents_rect_, visible_content_rect()); 64 return LayerImpl::VisibleContentOpaqueRegion(); 65 } 66 void SetOpaqueContentsRect(gfx::Rect opaque_contents_rect) { 67 override_opaque_contents_rect_ = true; 68 opaque_contents_rect_ = opaque_contents_rect; 69 } 70 71 private: 72 bool override_opaque_contents_rect_; 73 gfx::Rect opaque_contents_rect_; 74 }; 75 76 static inline bool LayerImplDrawTransformIsUnknown(const Layer* layer) { 77 return layer->draw_transform_is_animating(); 78 } 79 static inline bool LayerImplDrawTransformIsUnknown(const LayerImpl* layer) { 80 return false; 81 } 82 83 template <typename LayerType, typename RenderSurfaceType> 84 class TestOcclusionTrackerWithClip 85 : public TestOcclusionTrackerBase<LayerType, RenderSurfaceType> { 86 public: 87 TestOcclusionTrackerWithClip(gfx::Rect viewport_rect, 88 bool record_metrics_for_frame) 89 : TestOcclusionTrackerBase<LayerType, RenderSurfaceType>( 90 viewport_rect, 91 record_metrics_for_frame) {} 92 explicit TestOcclusionTrackerWithClip(gfx::Rect viewport_rect) 93 : TestOcclusionTrackerBase<LayerType, RenderSurfaceType>(viewport_rect, 94 false) {} 95 96 bool OccludedLayer(const LayerType* layer, 97 gfx::Rect content_rect) const { 98 DCHECK(layer->visible_content_rect().Contains(content_rect)); 99 return this->Occluded(layer->render_target(), 100 content_rect, 101 layer->draw_transform(), 102 LayerImplDrawTransformIsUnknown(layer)); 103 } 104 105 // Gives an unoccluded sub-rect of |content_rect| in the content space of the 106 // layer. Simple wrapper around UnoccludedContentRect. 107 gfx::Rect UnoccludedLayerContentRect(const LayerType* layer, 108 gfx::Rect content_rect) const { 109 DCHECK(layer->visible_content_rect().Contains(content_rect)); 110 return this->UnoccludedContentRect( 111 layer->render_target(), 112 content_rect, 113 layer->draw_transform(), 114 LayerImplDrawTransformIsUnknown(layer)); 115 } 116 }; 117 118 struct OcclusionTrackerTestMainThreadTypes { 119 typedef Layer LayerType; 120 typedef FakeLayerTreeHost HostType; 121 typedef RenderSurface RenderSurfaceType; 122 typedef TestContentLayer ContentLayerType; 123 typedef scoped_refptr<Layer> LayerPtrType; 124 typedef scoped_refptr<ContentLayerType> ContentLayerPtrType; 125 typedef LayerIterator<Layer, 126 RenderSurfaceLayerList, 127 RenderSurface, 128 LayerIteratorActions::FrontToBack> TestLayerIterator; 129 typedef OcclusionTracker OcclusionTrackerType; 130 131 static LayerPtrType CreateLayer(HostType* host) { return Layer::Create(); } 132 static ContentLayerPtrType CreateContentLayer(HostType* host) { 133 return make_scoped_refptr(new ContentLayerType()); 134 } 135 136 static LayerPtrType PassLayerPtr(ContentLayerPtrType* layer) { 137 LayerPtrType ref(*layer); 138 *layer = NULL; 139 return ref; 140 } 141 142 static LayerPtrType PassLayerPtr(LayerPtrType* layer) { 143 LayerPtrType ref(*layer); 144 *layer = NULL; 145 return ref; 146 } 147 148 static void DestroyLayer(LayerPtrType* layer) { *layer = NULL; } 149 }; 150 151 struct OcclusionTrackerTestImplThreadTypes { 152 typedef LayerImpl LayerType; 153 typedef LayerTreeImpl HostType; 154 typedef RenderSurfaceImpl RenderSurfaceType; 155 typedef TestContentLayerImpl ContentLayerType; 156 typedef scoped_ptr<LayerImpl> LayerPtrType; 157 typedef scoped_ptr<ContentLayerType> ContentLayerPtrType; 158 typedef LayerIterator<LayerImpl, 159 LayerImplList, 160 RenderSurfaceImpl, 161 LayerIteratorActions::FrontToBack> TestLayerIterator; 162 typedef OcclusionTrackerImpl OcclusionTrackerType; 163 164 static LayerPtrType CreateLayer(HostType* host) { 165 return LayerImpl::Create(host, next_layer_impl_id++); 166 } 167 static ContentLayerPtrType CreateContentLayer(HostType* host) { 168 return make_scoped_ptr(new ContentLayerType(host, next_layer_impl_id++)); 169 } 170 static int next_layer_impl_id; 171 172 static LayerPtrType PassLayerPtr(LayerPtrType* layer) { 173 return layer->Pass(); 174 } 175 176 static LayerPtrType PassLayerPtr(ContentLayerPtrType* layer) { 177 return layer->PassAs<LayerType>(); 178 } 179 180 static void DestroyLayer(LayerPtrType* layer) { layer->reset(); } 181 }; 182 183 int OcclusionTrackerTestImplThreadTypes::next_layer_impl_id = 1; 184 185 template <typename Types> class OcclusionTrackerTest : public testing::Test { 186 protected: 187 explicit OcclusionTrackerTest(bool opaque_layers) 188 : opaque_layers_(opaque_layers), host_(FakeLayerTreeHost::Create()) {} 189 190 virtual void RunMyTest() = 0; 191 192 virtual void TearDown() { 193 Types::DestroyLayer(&root_); 194 render_surface_layer_list_.reset(); 195 render_surface_layer_list_impl_.clear(); 196 replica_layers_.clear(); 197 mask_layers_.clear(); 198 } 199 200 typename Types::HostType* GetHost(); 201 202 typename Types::ContentLayerType* CreateRoot(const gfx::Transform& transform, 203 gfx::PointF position, 204 gfx::Size bounds) { 205 typename Types::ContentLayerPtrType layer( 206 Types::CreateContentLayer(GetHost())); 207 typename Types::ContentLayerType* layer_ptr = layer.get(); 208 SetProperties(layer_ptr, transform, position, bounds); 209 210 DCHECK(!root_.get()); 211 root_ = Types::PassLayerPtr(&layer); 212 213 SetRootLayerOnMainThread(layer_ptr); 214 215 return layer_ptr; 216 } 217 218 typename Types::LayerType* CreateLayer(typename Types::LayerType* parent, 219 const gfx::Transform& transform, 220 gfx::PointF position, 221 gfx::Size bounds) { 222 typename Types::LayerPtrType layer(Types::CreateLayer(GetHost())); 223 typename Types::LayerType* layer_ptr = layer.get(); 224 SetProperties(layer_ptr, transform, position, bounds); 225 parent->AddChild(Types::PassLayerPtr(&layer)); 226 return layer_ptr; 227 } 228 229 typename Types::LayerType* CreateSurface(typename Types::LayerType* parent, 230 const gfx::Transform& transform, 231 gfx::PointF position, 232 gfx::Size bounds) { 233 typename Types::LayerType* layer = 234 CreateLayer(parent, transform, position, bounds); 235 layer->SetForceRenderSurface(true); 236 return layer; 237 } 238 239 typename Types::ContentLayerType* CreateDrawingLayer( 240 typename Types::LayerType* parent, 241 const gfx::Transform& transform, 242 gfx::PointF position, 243 gfx::Size bounds, 244 bool opaque) { 245 typename Types::ContentLayerPtrType layer( 246 Types::CreateContentLayer(GetHost())); 247 typename Types::ContentLayerType* layer_ptr = layer.get(); 248 SetProperties(layer_ptr, transform, position, bounds); 249 250 if (opaque_layers_) { 251 layer_ptr->SetContentsOpaque(opaque); 252 } else { 253 layer_ptr->SetContentsOpaque(false); 254 if (opaque) 255 layer_ptr->SetOpaqueContentsRect(gfx::Rect(bounds)); 256 else 257 layer_ptr->SetOpaqueContentsRect(gfx::Rect()); 258 } 259 260 parent->AddChild(Types::PassLayerPtr(&layer)); 261 return layer_ptr; 262 } 263 264 typename Types::LayerType* CreateReplicaLayer( 265 typename Types::LayerType* owning_layer, 266 const gfx::Transform& transform, 267 gfx::PointF position, 268 gfx::Size bounds) { 269 typename Types::ContentLayerPtrType layer( 270 Types::CreateContentLayer(GetHost())); 271 typename Types::ContentLayerType* layer_ptr = layer.get(); 272 SetProperties(layer_ptr, transform, position, bounds); 273 SetReplica(owning_layer, Types::PassLayerPtr(&layer)); 274 return layer_ptr; 275 } 276 277 typename Types::LayerType* CreateMaskLayer( 278 typename Types::LayerType* owning_layer, 279 gfx::Size bounds) { 280 typename Types::ContentLayerPtrType layer( 281 Types::CreateContentLayer(GetHost())); 282 typename Types::ContentLayerType* layer_ptr = layer.get(); 283 SetProperties(layer_ptr, identity_matrix, gfx::PointF(), bounds); 284 SetMask(owning_layer, Types::PassLayerPtr(&layer)); 285 return layer_ptr; 286 } 287 288 typename Types::ContentLayerType* CreateDrawingSurface( 289 typename Types::LayerType* parent, 290 const gfx::Transform& transform, 291 gfx::PointF position, 292 gfx::Size bounds, 293 bool opaque) { 294 typename Types::ContentLayerType* layer = 295 CreateDrawingLayer(parent, transform, position, bounds, opaque); 296 layer->SetForceRenderSurface(true); 297 return layer; 298 } 299 300 301 void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {} 302 303 void AddCopyRequest(Layer* layer) { 304 layer->RequestCopyOfOutput( 305 CopyOutputRequest::CreateBitmapRequest(base::Bind( 306 &OcclusionTrackerTest<Types>::CopyOutputCallback, 307 base::Unretained(this)))); 308 } 309 310 void AddCopyRequest(LayerImpl* layer) { 311 ScopedPtrVector<CopyOutputRequest> requests; 312 requests.push_back( 313 CopyOutputRequest::CreateBitmapRequest(base::Bind( 314 &OcclusionTrackerTest<Types>::CopyOutputCallback, 315 base::Unretained(this)))); 316 layer->PassCopyRequests(&requests); 317 } 318 319 void CalcDrawEtc(TestContentLayerImpl* root) { 320 DCHECK(root == root_.get()); 321 DCHECK(!root->render_surface()); 322 323 LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs( 324 root, root->bounds(), &render_surface_layer_list_impl_); 325 inputs.can_adjust_raster_scales = true; 326 LayerTreeHostCommon::CalculateDrawProperties(&inputs); 327 328 layer_iterator_ = layer_iterator_begin_ = 329 Types::TestLayerIterator::Begin(&render_surface_layer_list_impl_); 330 } 331 332 void CalcDrawEtc(TestContentLayer* root) { 333 DCHECK(root == root_.get()); 334 DCHECK(!root->render_surface()); 335 336 render_surface_layer_list_.reset(new RenderSurfaceLayerList); 337 LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs( 338 root, root->bounds(), render_surface_layer_list_.get()); 339 inputs.can_adjust_raster_scales = true; 340 LayerTreeHostCommon::CalculateDrawProperties(&inputs); 341 342 layer_iterator_ = layer_iterator_begin_ = 343 Types::TestLayerIterator::Begin(render_surface_layer_list_.get()); 344 } 345 346 void SetDrawsContent(LayerImpl* layer_impl, bool draws_content) { 347 layer_impl->SetDrawsContent(draws_content); 348 } 349 350 void SetDrawsContent(Layer* layer, bool draws_content) { 351 layer->SetIsDrawable(draws_content); 352 } 353 354 void EnterLayer(typename Types::LayerType* layer, 355 typename Types::OcclusionTrackerType* occlusion) { 356 ASSERT_EQ(layer, *layer_iterator_); 357 ASSERT_TRUE(layer_iterator_.represents_itself()); 358 occlusion->EnterLayer(layer_iterator_); 359 } 360 361 void LeaveLayer(typename Types::LayerType* layer, 362 typename Types::OcclusionTrackerType* occlusion) { 363 ASSERT_EQ(layer, *layer_iterator_); 364 ASSERT_TRUE(layer_iterator_.represents_itself()); 365 occlusion->LeaveLayer(layer_iterator_); 366 ++layer_iterator_; 367 } 368 369 void VisitLayer(typename Types::LayerType* layer, 370 typename Types::OcclusionTrackerType* occlusion) { 371 EnterLayer(layer, occlusion); 372 LeaveLayer(layer, occlusion); 373 } 374 375 void EnterContributingSurface( 376 typename Types::LayerType* layer, 377 typename Types::OcclusionTrackerType* occlusion) { 378 ASSERT_EQ(layer, *layer_iterator_); 379 ASSERT_TRUE(layer_iterator_.represents_target_render_surface()); 380 occlusion->EnterLayer(layer_iterator_); 381 occlusion->LeaveLayer(layer_iterator_); 382 ++layer_iterator_; 383 ASSERT_TRUE(layer_iterator_.represents_contributing_render_surface()); 384 occlusion->EnterLayer(layer_iterator_); 385 } 386 387 void LeaveContributingSurface( 388 typename Types::LayerType* layer, 389 typename Types::OcclusionTrackerType* occlusion) { 390 ASSERT_EQ(layer, *layer_iterator_); 391 ASSERT_TRUE(layer_iterator_.represents_contributing_render_surface()); 392 occlusion->LeaveLayer(layer_iterator_); 393 ++layer_iterator_; 394 } 395 396 void VisitContributingSurface( 397 typename Types::LayerType* layer, 398 typename Types::OcclusionTrackerType* occlusion) { 399 EnterContributingSurface(layer, occlusion); 400 LeaveContributingSurface(layer, occlusion); 401 } 402 403 void ResetLayerIterator() { layer_iterator_ = layer_iterator_begin_; } 404 405 const gfx::Transform identity_matrix; 406 407 private: 408 void SetRootLayerOnMainThread(Layer* root) { 409 host_->SetRootLayer(scoped_refptr<Layer>(root)); 410 } 411 412 void SetRootLayerOnMainThread(LayerImpl* root) {} 413 414 void SetBaseProperties(typename Types::LayerType* layer, 415 const gfx::Transform& transform, 416 gfx::PointF position, 417 gfx::Size bounds) { 418 layer->SetTransform(transform); 419 layer->SetSublayerTransform(gfx::Transform()); 420 layer->SetAnchorPoint(gfx::PointF()); 421 layer->SetPosition(position); 422 layer->SetBounds(bounds); 423 } 424 425 void SetProperties(Layer* layer, 426 const gfx::Transform& transform, 427 gfx::PointF position, 428 gfx::Size bounds) { 429 SetBaseProperties(layer, transform, position, bounds); 430 } 431 432 void SetProperties(LayerImpl* layer, 433 const gfx::Transform& transform, 434 gfx::PointF position, 435 gfx::Size bounds) { 436 SetBaseProperties(layer, transform, position, bounds); 437 438 layer->SetContentBounds(layer->bounds()); 439 } 440 441 void SetReplica(Layer* owning_layer, scoped_refptr<Layer> layer) { 442 owning_layer->SetReplicaLayer(layer.get()); 443 replica_layers_.push_back(layer); 444 } 445 446 void SetReplica(LayerImpl* owning_layer, scoped_ptr<LayerImpl> layer) { 447 owning_layer->SetReplicaLayer(layer.Pass()); 448 } 449 450 void SetMask(Layer* owning_layer, scoped_refptr<Layer> layer) { 451 owning_layer->SetMaskLayer(layer.get()); 452 mask_layers_.push_back(layer); 453 } 454 455 void SetMask(LayerImpl* owning_layer, scoped_ptr<LayerImpl> layer) { 456 owning_layer->SetMaskLayer(layer.Pass()); 457 } 458 459 bool opaque_layers_; 460 scoped_ptr<FakeLayerTreeHost> host_; 461 // These hold ownership of the layers for the duration of the test. 462 typename Types::LayerPtrType root_; 463 scoped_ptr<RenderSurfaceLayerList> render_surface_layer_list_; 464 LayerImplList render_surface_layer_list_impl_; 465 typename Types::TestLayerIterator layer_iterator_begin_; 466 typename Types::TestLayerIterator layer_iterator_; 467 typename Types::LayerType* last_layer_visited_; 468 LayerList replica_layers_; 469 LayerList mask_layers_; 470 }; 471 472 template <> 473 FakeLayerTreeHost* 474 OcclusionTrackerTest<OcclusionTrackerTestMainThreadTypes>::GetHost() { 475 return host_.get(); 476 } 477 478 template <> 479 LayerTreeImpl* 480 OcclusionTrackerTest<OcclusionTrackerTestImplThreadTypes>::GetHost() { 481 return host_->host_impl()->active_tree(); 482 } 483 484 #define RUN_TEST_MAIN_THREAD_OPAQUE_LAYERS(ClassName) \ 485 class ClassName##MainThreadOpaqueLayers \ 486 : public ClassName<OcclusionTrackerTestMainThreadTypes> { \ 487 public: /* NOLINT(whitespace/indent) */ \ 488 ClassName##MainThreadOpaqueLayers() \ 489 : ClassName<OcclusionTrackerTestMainThreadTypes>(true) {} \ 490 }; \ 491 TEST_F(ClassName##MainThreadOpaqueLayers, RunTest) { RunMyTest(); } 492 #define RUN_TEST_MAIN_THREAD_OPAQUE_PAINTS(ClassName) \ 493 class ClassName##MainThreadOpaquePaints \ 494 : public ClassName<OcclusionTrackerTestMainThreadTypes> { \ 495 public: /* NOLINT(whitespace/indent) */ \ 496 ClassName##MainThreadOpaquePaints() \ 497 : ClassName<OcclusionTrackerTestMainThreadTypes>(false) {} \ 498 }; \ 499 TEST_F(ClassName##MainThreadOpaquePaints, RunTest) { RunMyTest(); } 500 501 #define RUN_TEST_IMPL_THREAD_OPAQUE_LAYERS(ClassName) \ 502 class ClassName##ImplThreadOpaqueLayers \ 503 : public ClassName<OcclusionTrackerTestImplThreadTypes> { \ 504 public: /* NOLINT(whitespace/indent) */ \ 505 ClassName##ImplThreadOpaqueLayers() \ 506 : ClassName<OcclusionTrackerTestImplThreadTypes>(true) {} \ 507 }; \ 508 TEST_F(ClassName##ImplThreadOpaqueLayers, RunTest) { RunMyTest(); } 509 #define RUN_TEST_IMPL_THREAD_OPAQUE_PAINTS(ClassName) \ 510 class ClassName##ImplThreadOpaquePaints \ 511 : public ClassName<OcclusionTrackerTestImplThreadTypes> { \ 512 public: /* NOLINT(whitespace/indent) */ \ 513 ClassName##ImplThreadOpaquePaints() \ 514 : ClassName<OcclusionTrackerTestImplThreadTypes>(false) {} \ 515 }; \ 516 TEST_F(ClassName##ImplThreadOpaquePaints, RunTest) { RunMyTest(); } 517 518 #define ALL_OCCLUSIONTRACKER_TEST(ClassName) \ 519 RUN_TEST_MAIN_THREAD_OPAQUE_LAYERS(ClassName) \ 520 RUN_TEST_MAIN_THREAD_OPAQUE_PAINTS(ClassName) \ 521 RUN_TEST_IMPL_THREAD_OPAQUE_LAYERS(ClassName) \ 522 RUN_TEST_IMPL_THREAD_OPAQUE_PAINTS(ClassName) 523 524 #define MAIN_THREAD_TEST(ClassName) \ 525 RUN_TEST_MAIN_THREAD_OPAQUE_LAYERS(ClassName) 526 527 #define IMPL_THREAD_TEST(ClassName) \ 528 RUN_TEST_IMPL_THREAD_OPAQUE_LAYERS(ClassName) 529 530 #define MAIN_AND_IMPL_THREAD_TEST(ClassName) \ 531 RUN_TEST_MAIN_THREAD_OPAQUE_LAYERS(ClassName) \ 532 RUN_TEST_IMPL_THREAD_OPAQUE_LAYERS(ClassName) 533 534 template <class Types> 535 class OcclusionTrackerTestIdentityTransforms 536 : public OcclusionTrackerTest<Types> { 537 protected: 538 explicit OcclusionTrackerTestIdentityTransforms(bool opaque_layers) 539 : OcclusionTrackerTest<Types>(opaque_layers) {} 540 541 void RunMyTest() { 542 typename Types::ContentLayerType* root = this->CreateRoot( 543 this->identity_matrix, gfx::PointF(), gfx::Size(200, 200)); 544 typename Types::ContentLayerType* parent = this->CreateDrawingLayer( 545 root, this->identity_matrix, gfx::PointF(), gfx::Size(100, 100), true); 546 typename Types::ContentLayerType* layer = 547 this->CreateDrawingLayer(parent, 548 this->identity_matrix, 549 gfx::PointF(30.f, 30.f), 550 gfx::Size(500, 500), 551 true); 552 parent->SetMasksToBounds(true); 553 this->CalcDrawEtc(root); 554 555 TestOcclusionTrackerWithClip<typename Types::LayerType, 556 typename Types::RenderSurfaceType> occlusion( 557 gfx::Rect(0, 0, 1000, 1000), false); 558 559 this->VisitLayer(layer, &occlusion); 560 this->EnterLayer(parent, &occlusion); 561 562 EXPECT_EQ(gfx::Rect().ToString(), 563 occlusion.occlusion_from_outside_target().ToString()); 564 EXPECT_EQ(gfx::Rect(30, 30, 70, 70).ToString(), 565 occlusion.occlusion_from_inside_target().ToString()); 566 567 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 30, 70, 70))); 568 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 30, 70, 70))); 569 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 29, 70, 70))); 570 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(31, 30, 69, 70))); 571 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 31, 70, 69))); 572 573 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect( 574 parent, gfx::Rect(30, 30, 70, 70)).IsEmpty()); 575 EXPECT_RECT_EQ(gfx::Rect(29, 30, 1, 70), 576 occlusion.UnoccludedLayerContentRect( 577 parent, gfx::Rect(29, 30, 70, 70))); 578 EXPECT_RECT_EQ(gfx::Rect(29, 29, 70, 70), 579 occlusion.UnoccludedLayerContentRect( 580 parent, gfx::Rect(29, 29, 70, 70))); 581 EXPECT_RECT_EQ(gfx::Rect(30, 29, 70, 1), 582 occlusion.UnoccludedLayerContentRect( 583 parent, gfx::Rect(30, 29, 70, 70))); 584 EXPECT_RECT_EQ(gfx::Rect(31, 29, 69, 1), 585 occlusion.UnoccludedLayerContentRect( 586 parent, gfx::Rect(31, 29, 69, 70))); 587 EXPECT_RECT_EQ(gfx::Rect(), 588 occlusion.UnoccludedLayerContentRect( 589 parent, gfx::Rect(31, 30, 69, 70))); 590 EXPECT_RECT_EQ(gfx::Rect(), 591 occlusion.UnoccludedLayerContentRect( 592 parent, gfx::Rect(31, 31, 69, 69))); 593 EXPECT_RECT_EQ(gfx::Rect(), 594 occlusion.UnoccludedLayerContentRect( 595 parent, gfx::Rect(30, 31, 70, 69))); 596 EXPECT_RECT_EQ(gfx::Rect(29, 31, 1, 69), 597 occlusion.UnoccludedLayerContentRect( 598 parent, gfx::Rect(29, 31, 70, 69))); 599 } 600 }; 601 602 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestIdentityTransforms); 603 604 template <class Types> 605 class OcclusionTrackerTestQuadsMismatchLayer 606 : public OcclusionTrackerTest<Types> { 607 protected: 608 explicit OcclusionTrackerTestQuadsMismatchLayer(bool opaque_layers) 609 : OcclusionTrackerTest<Types>(opaque_layers) {} 610 void RunMyTest() { 611 gfx::Transform layer_transform; 612 layer_transform.Translate(10.0, 10.0); 613 614 typename Types::ContentLayerType* parent = this->CreateRoot( 615 this->identity_matrix, gfx::Point(0, 0), gfx::Size(100, 100)); 616 typename Types::ContentLayerType* layer1 = this->CreateDrawingLayer( 617 parent, layer_transform, gfx::PointF(), gfx::Size(90, 90), true); 618 typename Types::ContentLayerType* layer2 = this->CreateDrawingLayer( 619 layer1, layer_transform, gfx::PointF(), gfx::Size(50, 50), true); 620 this->CalcDrawEtc(parent); 621 622 TestOcclusionTrackerWithClip<typename Types::LayerType, 623 typename Types::RenderSurfaceType> occlusion( 624 gfx::Rect(0, 0, 1000, 1000)); 625 626 this->VisitLayer(layer2, &occlusion); 627 this->EnterLayer(layer1, &occlusion); 628 629 EXPECT_EQ(gfx::Rect().ToString(), 630 occlusion.occlusion_from_outside_target().ToString()); 631 EXPECT_EQ(gfx::Rect(20, 20, 50, 50).ToString(), 632 occlusion.occlusion_from_inside_target().ToString()); 633 634 // This checks cases where the quads don't match their "containing" 635 // layers, e.g. in terms of transforms or clip rect. This is typical for 636 // DelegatedRendererLayer. 637 638 gfx::Transform quad_transform; 639 quad_transform.Translate(30.0, 30.0); 640 641 EXPECT_TRUE(occlusion.UnoccludedContentRect(parent, 642 gfx::Rect(0, 0, 10, 10), 643 quad_transform, 644 false).IsEmpty()); 645 EXPECT_RECT_EQ(gfx::Rect(0, 0, 10, 10), 646 occlusion.UnoccludedContentRect(parent, 647 gfx::Rect(0, 0, 10, 10), 648 quad_transform, 649 true)); 650 EXPECT_RECT_EQ(gfx::Rect(40, 40, 10, 10), 651 occlusion.UnoccludedContentRect(parent, 652 gfx::Rect(40, 40, 10, 10), 653 quad_transform, 654 false)); 655 EXPECT_RECT_EQ(gfx::Rect(40, 30, 5, 10), 656 occlusion.UnoccludedContentRect(parent, 657 gfx::Rect(35, 30, 10, 10), 658 quad_transform, 659 false)); 660 } 661 }; 662 663 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestQuadsMismatchLayer); 664 665 template <class Types> 666 class OcclusionTrackerTestRotatedChild : public OcclusionTrackerTest<Types> { 667 protected: 668 explicit OcclusionTrackerTestRotatedChild(bool opaque_layers) 669 : OcclusionTrackerTest<Types>(opaque_layers) {} 670 void RunMyTest() { 671 gfx::Transform layer_transform; 672 layer_transform.Translate(250.0, 250.0); 673 layer_transform.Rotate(90.0); 674 layer_transform.Translate(-250.0, -250.0); 675 676 typename Types::ContentLayerType* root = this->CreateRoot( 677 this->identity_matrix, gfx::Point(0, 0), gfx::Size(200, 200)); 678 typename Types::ContentLayerType* parent = this->CreateDrawingLayer( 679 root, this->identity_matrix, gfx::PointF(), gfx::Size(100, 100), true); 680 typename Types::ContentLayerType* layer = 681 this->CreateDrawingLayer(parent, 682 layer_transform, 683 gfx::PointF(30.f, 30.f), 684 gfx::Size(500, 500), 685 true); 686 parent->SetMasksToBounds(true); 687 this->CalcDrawEtc(root); 688 689 TestOcclusionTrackerWithClip<typename Types::LayerType, 690 typename Types::RenderSurfaceType> occlusion( 691 gfx::Rect(0, 0, 1000, 1000)); 692 693 this->VisitLayer(layer, &occlusion); 694 this->EnterLayer(parent, &occlusion); 695 696 EXPECT_EQ(gfx::Rect().ToString(), 697 occlusion.occlusion_from_outside_target().ToString()); 698 EXPECT_EQ(gfx::Rect(30, 30, 70, 70).ToString(), 699 occlusion.occlusion_from_inside_target().ToString()); 700 701 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 30, 70, 70))); 702 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 30, 70, 70))); 703 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 29, 70, 70))); 704 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(31, 30, 69, 70))); 705 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 31, 70, 69))); 706 707 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect( 708 parent, gfx::Rect(30, 30, 70, 70)).IsEmpty()); 709 EXPECT_RECT_EQ(gfx::Rect(29, 30, 1, 70), 710 occlusion.UnoccludedLayerContentRect( 711 parent, gfx::Rect(29, 30, 69, 70))); 712 EXPECT_RECT_EQ(gfx::Rect(29, 29, 70, 70), 713 occlusion.UnoccludedLayerContentRect( 714 parent, gfx::Rect(29, 29, 70, 70))); 715 EXPECT_RECT_EQ(gfx::Rect(30, 29, 70, 1), 716 occlusion.UnoccludedLayerContentRect( 717 parent, gfx::Rect(30, 29, 70, 70))); 718 EXPECT_RECT_EQ(gfx::Rect(31, 29, 69, 1), 719 occlusion.UnoccludedLayerContentRect( 720 parent, gfx::Rect(31, 29, 69, 70))); 721 EXPECT_RECT_EQ(gfx::Rect(), 722 occlusion.UnoccludedLayerContentRect( 723 parent, gfx::Rect(31, 30, 69, 70))); 724 EXPECT_RECT_EQ(gfx::Rect(), 725 occlusion.UnoccludedLayerContentRect( 726 parent, gfx::Rect(31, 31, 69, 69))); 727 EXPECT_RECT_EQ(gfx::Rect(), 728 occlusion.UnoccludedLayerContentRect( 729 parent, gfx::Rect(30, 31, 70, 69))); 730 EXPECT_RECT_EQ(gfx::Rect(29, 31, 1, 69), 731 occlusion.UnoccludedLayerContentRect( 732 parent, gfx::Rect(29, 31, 70, 69))); 733 } 734 }; 735 736 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestRotatedChild); 737 738 template <class Types> 739 class OcclusionTrackerTestTranslatedChild : public OcclusionTrackerTest<Types> { 740 protected: 741 explicit OcclusionTrackerTestTranslatedChild(bool opaque_layers) 742 : OcclusionTrackerTest<Types>(opaque_layers) {} 743 void RunMyTest() { 744 gfx::Transform layer_transform; 745 layer_transform.Translate(20.0, 20.0); 746 747 typename Types::ContentLayerType* root = this->CreateRoot( 748 this->identity_matrix, gfx::PointF(), gfx::Size(200, 200)); 749 typename Types::ContentLayerType* parent = this->CreateDrawingLayer( 750 root, this->identity_matrix, gfx::PointF(), gfx::Size(100, 100), true); 751 typename Types::ContentLayerType* layer = 752 this->CreateDrawingLayer(parent, 753 layer_transform, 754 gfx::PointF(30.f, 30.f), 755 gfx::Size(500, 500), 756 true); 757 parent->SetMasksToBounds(true); 758 this->CalcDrawEtc(root); 759 760 TestOcclusionTrackerWithClip<typename Types::LayerType, 761 typename Types::RenderSurfaceType> occlusion( 762 gfx::Rect(0, 0, 1000, 1000)); 763 764 this->VisitLayer(layer, &occlusion); 765 this->EnterLayer(parent, &occlusion); 766 767 EXPECT_EQ(gfx::Rect().ToString(), 768 occlusion.occlusion_from_outside_target().ToString()); 769 EXPECT_EQ(gfx::Rect(50, 50, 50, 50).ToString(), 770 occlusion.occlusion_from_inside_target().ToString()); 771 772 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(50, 50, 50, 50))); 773 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(49, 50, 50, 50))); 774 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(50, 49, 50, 50))); 775 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(51, 50, 49, 50))); 776 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(50, 51, 50, 49))); 777 778 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect( 779 parent, gfx::Rect(50, 50, 50, 50)).IsEmpty()); 780 EXPECT_RECT_EQ(gfx::Rect(49, 50, 1, 50), 781 occlusion.UnoccludedLayerContentRect( 782 parent, gfx::Rect(49, 50, 50, 50))); 783 EXPECT_RECT_EQ(gfx::Rect(49, 49, 50, 50), 784 occlusion.UnoccludedLayerContentRect( 785 parent, gfx::Rect(49, 49, 50, 50))); 786 EXPECT_RECT_EQ(gfx::Rect(50, 49, 50, 1), 787 occlusion.UnoccludedLayerContentRect( 788 parent, gfx::Rect(50, 49, 50, 50))); 789 EXPECT_RECT_EQ(gfx::Rect(51, 49, 49, 1), 790 occlusion.UnoccludedLayerContentRect( 791 parent, gfx::Rect(51, 49, 49, 50))); 792 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect( 793 parent, gfx::Rect(51, 50, 49, 50)).IsEmpty()); 794 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect( 795 parent, gfx::Rect(51, 51, 49, 49)).IsEmpty()); 796 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect( 797 parent, gfx::Rect(50, 51, 50, 49)).IsEmpty()); 798 EXPECT_RECT_EQ(gfx::Rect(49, 51, 1, 49), 799 occlusion.UnoccludedLayerContentRect( 800 parent, gfx::Rect(49, 51, 50, 49))); 801 } 802 }; 803 804 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestTranslatedChild); 805 806 template <class Types> 807 class OcclusionTrackerTestChildInRotatedChild 808 : public OcclusionTrackerTest<Types> { 809 protected: 810 explicit OcclusionTrackerTestChildInRotatedChild(bool opaque_layers) 811 : OcclusionTrackerTest<Types>(opaque_layers) {} 812 void RunMyTest() { 813 gfx::Transform child_transform; 814 child_transform.Translate(250.0, 250.0); 815 child_transform.Rotate(90.0); 816 child_transform.Translate(-250.0, -250.0); 817 818 typename Types::ContentLayerType* parent = this->CreateRoot( 819 this->identity_matrix, gfx::PointF(), gfx::Size(100, 100)); 820 parent->SetMasksToBounds(true); 821 typename Types::LayerType* child = this->CreateSurface( 822 parent, child_transform, gfx::PointF(30.f, 30.f), gfx::Size(500, 500)); 823 child->SetMasksToBounds(true); 824 typename Types::ContentLayerType* layer = 825 this->CreateDrawingLayer(child, 826 this->identity_matrix, 827 gfx::PointF(10.f, 10.f), 828 gfx::Size(500, 500), 829 true); 830 this->CalcDrawEtc(parent); 831 832 TestOcclusionTrackerWithClip<typename Types::LayerType, 833 typename Types::RenderSurfaceType> occlusion( 834 gfx::Rect(0, 0, 1000, 1000)); 835 836 this->VisitLayer(layer, &occlusion); 837 this->EnterContributingSurface(child, &occlusion); 838 839 EXPECT_EQ(gfx::Rect().ToString(), 840 occlusion.occlusion_from_outside_target().ToString()); 841 EXPECT_EQ(gfx::Rect(10, 430, 60, 70).ToString(), 842 occlusion.occlusion_from_inside_target().ToString()); 843 844 this->LeaveContributingSurface(child, &occlusion); 845 this->EnterLayer(parent, &occlusion); 846 847 EXPECT_EQ(gfx::Rect().ToString(), 848 occlusion.occlusion_from_outside_target().ToString()); 849 EXPECT_EQ(gfx::Rect(30, 40, 70, 60).ToString(), 850 occlusion.occlusion_from_inside_target().ToString()); 851 852 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 40, 70, 60))); 853 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 40, 70, 60))); 854 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 39, 70, 60))); 855 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(31, 40, 69, 60))); 856 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 41, 70, 59))); 857 858 /* Justification for the above occlusion from |layer|: 859 100 860 +---------------------+ 861 | | 862 | 30 | rotate(90) 863 | 30 + ---------------------------------+ 864 100 | | 10 | | ==> 865 | |10+---------------------------------+ 866 | | | | | | 867 | | | | | | 868 | | | | | | 869 +----|--|-------------+ | | 870 | | | | 871 | | | | 872 | | | |500 873 | | | | 874 | | | | 875 | | | | 876 | | | | 877 +--|-------------------------------+ | 878 | | 879 +---------------------------------+ 880 500 881 882 +---------------------+ 883 | |30 Visible region of |layer|: ///// 884 | | 885 | +---------------------------------+ 886 100| | |10 | 887 | +---------------------------------+ | 888 | | |///////////////| 420 | | 889 | | |///////////////|60 | | 890 | | |///////////////| | | 891 +--|--|---------------+ | | 892 20|10| 70 | | 893 | | | | 894 | | | | 895 | | | | 896 | | | | 897 | | | | 898 | | |10| 899 | +------------------------------|--+ 900 | 490 | 901 +---------------------------------+ 902 500 903 904 */ 905 } 906 }; 907 908 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestChildInRotatedChild); 909 910 template <class Types> 911 class OcclusionTrackerTestScaledRenderSurface 912 : public OcclusionTrackerTest<Types> { 913 protected: 914 explicit OcclusionTrackerTestScaledRenderSurface(bool opaque_layers) 915 : OcclusionTrackerTest<Types>(opaque_layers) {} 916 917 void RunMyTest() { 918 typename Types::ContentLayerType* parent = this->CreateRoot( 919 this->identity_matrix, gfx::PointF(), gfx::Size(200, 200)); 920 921 gfx::Transform layer1_matrix; 922 layer1_matrix.Scale(2.0, 2.0); 923 typename Types::ContentLayerType* layer1 = this->CreateDrawingLayer( 924 parent, layer1_matrix, gfx::PointF(), gfx::Size(100, 100), true); 925 layer1->SetForceRenderSurface(true); 926 927 gfx::Transform layer2_matrix; 928 layer2_matrix.Translate(25.0, 25.0); 929 typename Types::ContentLayerType* layer2 = this->CreateDrawingLayer( 930 layer1, layer2_matrix, gfx::PointF(), gfx::Size(50, 50), true); 931 typename Types::ContentLayerType* occluder = 932 this->CreateDrawingLayer(parent, 933 this->identity_matrix, 934 gfx::PointF(100.f, 100.f), 935 gfx::Size(500, 500), 936 true); 937 this->CalcDrawEtc(parent); 938 939 TestOcclusionTrackerWithClip<typename Types::LayerType, 940 typename Types::RenderSurfaceType> occlusion( 941 gfx::Rect(0, 0, 1000, 1000)); 942 943 this->VisitLayer(occluder, &occlusion); 944 this->EnterLayer(layer2, &occlusion); 945 946 EXPECT_EQ(gfx::Rect(100, 100, 100, 100).ToString(), 947 occlusion.occlusion_from_outside_target().ToString()); 948 EXPECT_EQ(gfx::Rect().ToString(), 949 occlusion.occlusion_from_inside_target().ToString()); 950 951 EXPECT_RECT_EQ( 952 gfx::Rect(0, 0, 25, 25), 953 occlusion.UnoccludedLayerContentRect(layer2, gfx::Rect(0, 0, 25, 25))); 954 EXPECT_RECT_EQ(gfx::Rect(10, 25, 15, 25), 955 occlusion.UnoccludedLayerContentRect( 956 layer2, gfx::Rect(10, 25, 25, 25))); 957 EXPECT_RECT_EQ(gfx::Rect(25, 10, 25, 15), 958 occlusion.UnoccludedLayerContentRect( 959 layer2, gfx::Rect(25, 10, 25, 25))); 960 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect( 961 layer2, gfx::Rect(25, 25, 25, 25)).IsEmpty()); 962 } 963 }; 964 965 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestScaledRenderSurface); 966 967 template <class Types> 968 class OcclusionTrackerTestVisitTargetTwoTimes 969 : public OcclusionTrackerTest<Types> { 970 protected: 971 explicit OcclusionTrackerTestVisitTargetTwoTimes(bool opaque_layers) 972 : OcclusionTrackerTest<Types>(opaque_layers) {} 973 void RunMyTest() { 974 gfx::Transform child_transform; 975 child_transform.Translate(250.0, 250.0); 976 child_transform.Rotate(90.0); 977 child_transform.Translate(-250.0, -250.0); 978 979 typename Types::ContentLayerType* root = this->CreateRoot( 980 this->identity_matrix, gfx::PointF(), gfx::Size(200, 200)); 981 typename Types::ContentLayerType* parent = this->CreateDrawingLayer( 982 root, this->identity_matrix, gfx::PointF(), gfx::Size(100, 100), true); 983 parent->SetMasksToBounds(true); 984 typename Types::LayerType* child = this->CreateSurface( 985 parent, child_transform, gfx::PointF(30.f, 30.f), gfx::Size(500, 500)); 986 child->SetMasksToBounds(true); 987 typename Types::ContentLayerType* layer = 988 this->CreateDrawingLayer(child, 989 this->identity_matrix, 990 gfx::PointF(10.f, 10.f), 991 gfx::Size(500, 500), 992 true); 993 // |child2| makes |parent|'s surface get considered by OcclusionTracker 994 // first, instead of |child|'s. This exercises different code in 995 // LeaveToRenderTarget, as the target surface has already been seen. 996 typename Types::ContentLayerType* child2 = 997 this->CreateDrawingLayer(parent, 998 this->identity_matrix, 999 gfx::PointF(30.f, 30.f), 1000 gfx::Size(60, 20), 1001 true); 1002 this->CalcDrawEtc(root); 1003 1004 TestOcclusionTrackerWithClip<typename Types::LayerType, 1005 typename Types::RenderSurfaceType> occlusion( 1006 gfx::Rect(0, 0, 1000, 1000)); 1007 1008 this->VisitLayer(child2, &occlusion); 1009 1010 EXPECT_EQ(gfx::Rect().ToString(), 1011 occlusion.occlusion_from_outside_target().ToString()); 1012 EXPECT_EQ(gfx::Rect(30, 30, 60, 20).ToString(), 1013 occlusion.occlusion_from_inside_target().ToString()); 1014 1015 this->VisitLayer(layer, &occlusion); 1016 1017 EXPECT_EQ(gfx::Rect(0, 440, 20, 60).ToString(), 1018 occlusion.occlusion_from_outside_target().ToString()); 1019 EXPECT_EQ(gfx::Rect(10, 430, 60, 70).ToString(), 1020 occlusion.occlusion_from_inside_target().ToString()); 1021 1022 this->EnterContributingSurface(child, &occlusion); 1023 1024 EXPECT_EQ(gfx::Rect(0, 440, 20, 60).ToString(), 1025 occlusion.occlusion_from_outside_target().ToString()); 1026 EXPECT_EQ(gfx::Rect(10, 430, 60, 70).ToString(), 1027 occlusion.occlusion_from_inside_target().ToString()); 1028 1029 // Occlusion in |child2| should get merged with the |child| surface we are 1030 // leaving now. 1031 this->LeaveContributingSurface(child, &occlusion); 1032 this->EnterLayer(parent, &occlusion); 1033 1034 EXPECT_EQ(gfx::Rect().ToString(), 1035 occlusion.occlusion_from_outside_target().ToString()); 1036 EXPECT_EQ(UnionRegions(gfx::Rect(30, 30, 60, 10), gfx::Rect(30, 40, 70, 60)) 1037 .ToString(), 1038 occlusion.occlusion_from_inside_target().ToString()); 1039 1040 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 30, 70, 70))); 1041 EXPECT_RECT_EQ(gfx::Rect(90, 30, 10, 10), 1042 occlusion.UnoccludedLayerContentRect( 1043 parent, gfx::Rect(30, 30, 70, 70))); 1044 1045 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 30, 60, 10))); 1046 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 30, 60, 10))); 1047 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 29, 60, 10))); 1048 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(31, 30, 60, 10))); 1049 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 31, 60, 10))); 1050 1051 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 40, 70, 60))); 1052 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 40, 70, 60))); 1053 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 39, 70, 60))); 1054 1055 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect( 1056 parent, gfx::Rect(30, 30, 60, 10)).IsEmpty()); 1057 EXPECT_RECT_EQ(gfx::Rect(29, 30, 1, 10), 1058 occlusion.UnoccludedLayerContentRect( 1059 parent, gfx::Rect(29, 30, 60, 10))); 1060 EXPECT_RECT_EQ(gfx::Rect(30, 29, 60, 1), 1061 occlusion.UnoccludedLayerContentRect( 1062 parent, gfx::Rect(30, 29, 60, 10))); 1063 EXPECT_RECT_EQ(gfx::Rect(90, 30, 1, 10), 1064 occlusion.UnoccludedLayerContentRect( 1065 parent, gfx::Rect(31, 30, 60, 10))); 1066 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect( 1067 parent, gfx::Rect(30, 31, 60, 10)).IsEmpty()); 1068 1069 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect( 1070 parent, gfx::Rect(30, 40, 70, 60)).IsEmpty()); 1071 EXPECT_RECT_EQ(gfx::Rect(29, 40, 1, 60), 1072 occlusion.UnoccludedLayerContentRect( 1073 parent, gfx::Rect(29, 40, 70, 60))); 1074 // This rect is mostly occluded by |child2|. 1075 EXPECT_RECT_EQ(gfx::Rect(90, 39, 10, 1), 1076 occlusion.UnoccludedLayerContentRect( 1077 parent, gfx::Rect(30, 39, 70, 60))); 1078 // This rect extends past top/right ends of |child2|. 1079 EXPECT_RECT_EQ(gfx::Rect(30, 29, 70, 11), 1080 occlusion.UnoccludedLayerContentRect( 1081 parent, gfx::Rect(30, 29, 70, 70))); 1082 // This rect extends past left/right ends of |child2|. 1083 EXPECT_RECT_EQ(gfx::Rect(20, 39, 80, 60), 1084 occlusion.UnoccludedLayerContentRect( 1085 parent, gfx::Rect(20, 39, 80, 60))); 1086 EXPECT_RECT_EQ(gfx::Rect(), 1087 occlusion.UnoccludedLayerContentRect( 1088 parent, gfx::Rect(31, 40, 69, 60))); 1089 EXPECT_RECT_EQ(gfx::Rect(), 1090 occlusion.UnoccludedLayerContentRect( 1091 parent, gfx::Rect(30, 41, 70, 59))); 1092 1093 /* Justification for the above occlusion from |layer|: 1094 100 1095 +---------------------+ 1096 | | 1097 | 30 | rotate(90) 1098 | 30 + ------------+--------------------+ 1099 100 | | 10 | | | ==> 1100 | |10+----------|----------------------+ 1101 | + ------------+ | | | 1102 | | | | | | 1103 | | | | | | 1104 +----|--|-------------+ | | 1105 | | | | 1106 | | | | 1107 | | | |500 1108 | | | | 1109 | | | | 1110 | | | | 1111 | | | | 1112 +--|-------------------------------+ | 1113 | | 1114 +---------------------------------+ 1115 500 1116 1117 1118 +---------------------+ 1119 | |30 Visible region of |layer|: ///// 1120 | 30 60 | |child2|: \\\\\ 1121 | 30 +------------+--------------------+ 1122 | |\\\\\\\\\\\\| |10 | 1123 | +--|\\\\\\\\\\\\|-----------------+ | 1124 | | +------------+//| 420 | | 1125 | | |///////////////|60 | | 1126 | | |///////////////| | | 1127 +--|--|---------------+ | | 1128 20|10| 70 | | 1129 | | | | 1130 | | | | 1131 | | | | 1132 | | | | 1133 | | | | 1134 | | |10| 1135 | +------------------------------|--+ 1136 | 490 | 1137 +---------------------------------+ 1138 500 1139 */ 1140 } 1141 }; 1142 1143 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestVisitTargetTwoTimes); 1144 1145 template <class Types> 1146 class OcclusionTrackerTestSurfaceRotatedOffAxis 1147 : public OcclusionTrackerTest<Types> { 1148 protected: 1149 explicit OcclusionTrackerTestSurfaceRotatedOffAxis(bool opaque_layers) 1150 : OcclusionTrackerTest<Types>(opaque_layers) {} 1151 void RunMyTest() { 1152 gfx::Transform child_transform; 1153 child_transform.Translate(250.0, 250.0); 1154 child_transform.Rotate(95.0); 1155 child_transform.Translate(-250.0, -250.0); 1156 1157 gfx::Transform layer_transform; 1158 layer_transform.Translate(10.0, 10.0); 1159 1160 typename Types::ContentLayerType* root = this->CreateRoot( 1161 this->identity_matrix, gfx::PointF(), gfx::Size(1000, 1000)); 1162 typename Types::ContentLayerType* parent = this->CreateDrawingLayer( 1163 root, this->identity_matrix, gfx::PointF(), gfx::Size(100, 100), true); 1164 typename Types::LayerType* child = this->CreateLayer( 1165 parent, child_transform, gfx::PointF(30.f, 30.f), gfx::Size(500, 500)); 1166 child->SetMasksToBounds(true); 1167 typename Types::ContentLayerType* layer = this->CreateDrawingLayer( 1168 child, layer_transform, gfx::PointF(), gfx::Size(500, 500), true); 1169 this->CalcDrawEtc(root); 1170 1171 TestOcclusionTrackerWithClip<typename Types::LayerType, 1172 typename Types::RenderSurfaceType> occlusion( 1173 gfx::Rect(0, 0, 1000, 1000)); 1174 1175 gfx::Rect clipped_layer_in_child = MathUtil::MapClippedRect( 1176 layer_transform, layer->visible_content_rect()); 1177 1178 this->VisitLayer(layer, &occlusion); 1179 this->EnterContributingSurface(child, &occlusion); 1180 1181 EXPECT_EQ(gfx::Rect().ToString(), 1182 occlusion.occlusion_from_outside_target().ToString()); 1183 EXPECT_EQ(clipped_layer_in_child.ToString(), 1184 occlusion.occlusion_from_inside_target().ToString()); 1185 1186 this->LeaveContributingSurface(child, &occlusion); 1187 this->EnterLayer(parent, &occlusion); 1188 1189 EXPECT_EQ(gfx::Rect().ToString(), 1190 occlusion.occlusion_from_outside_target().ToString()); 1191 EXPECT_EQ(gfx::Rect().ToString(), 1192 occlusion.occlusion_from_inside_target().ToString()); 1193 1194 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(75, 55, 1, 1))); 1195 EXPECT_RECT_EQ( 1196 gfx::Rect(75, 55, 1, 1), 1197 occlusion.UnoccludedLayerContentRect(parent, gfx::Rect(75, 55, 1, 1))); 1198 } 1199 }; 1200 1201 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestSurfaceRotatedOffAxis); 1202 1203 template <class Types> 1204 class OcclusionTrackerTestSurfaceWithTwoOpaqueChildren 1205 : public OcclusionTrackerTest<Types> { 1206 protected: 1207 explicit OcclusionTrackerTestSurfaceWithTwoOpaqueChildren(bool opaque_layers) 1208 : OcclusionTrackerTest<Types>(opaque_layers) {} 1209 void RunMyTest() { 1210 gfx::Transform child_transform; 1211 child_transform.Translate(250.0, 250.0); 1212 child_transform.Rotate(90.0); 1213 child_transform.Translate(-250.0, -250.0); 1214 1215 typename Types::ContentLayerType* root = this->CreateRoot( 1216 this->identity_matrix, gfx::PointF(), gfx::Size(1000, 1000)); 1217 typename Types::ContentLayerType* parent = this->CreateDrawingLayer( 1218 root, this->identity_matrix, gfx::PointF(), gfx::Size(100, 100), true); 1219 parent->SetMasksToBounds(true); 1220 typename Types::ContentLayerType* child = 1221 this->CreateDrawingSurface(parent, 1222 child_transform, 1223 gfx::PointF(30.f, 30.f), 1224 gfx::Size(500, 500), 1225 false); 1226 child->SetMasksToBounds(true); 1227 typename Types::ContentLayerType* layer1 = 1228 this->CreateDrawingLayer(child, 1229 this->identity_matrix, 1230 gfx::PointF(10.f, 10.f), 1231 gfx::Size(500, 500), 1232 true); 1233 typename Types::ContentLayerType* layer2 = 1234 this->CreateDrawingLayer(child, 1235 this->identity_matrix, 1236 gfx::PointF(10.f, 450.f), 1237 gfx::Size(500, 60), 1238 true); 1239 this->CalcDrawEtc(root); 1240 1241 TestOcclusionTrackerWithClip<typename Types::LayerType, 1242 typename Types::RenderSurfaceType> occlusion( 1243 gfx::Rect(0, 0, 1000, 1000)); 1244 1245 this->VisitLayer(layer2, &occlusion); 1246 this->VisitLayer(layer1, &occlusion); 1247 this->VisitLayer(child, &occlusion); 1248 this->EnterContributingSurface(child, &occlusion); 1249 1250 EXPECT_EQ(gfx::Rect().ToString(), 1251 occlusion.occlusion_from_outside_target().ToString()); 1252 EXPECT_EQ(gfx::Rect(10, 430, 60, 70).ToString(), 1253 occlusion.occlusion_from_inside_target().ToString()); 1254 1255 EXPECT_TRUE(occlusion.OccludedLayer(child, gfx::Rect(10, 430, 60, 70))); 1256 EXPECT_FALSE(occlusion.OccludedLayer(child, gfx::Rect(9, 430, 60, 70))); 1257 EXPECT_TRUE(occlusion.OccludedLayer(child, gfx::Rect(11, 430, 59, 70))); 1258 EXPECT_TRUE(occlusion.OccludedLayer(child, gfx::Rect(10, 431, 60, 69))); 1259 1260 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect( 1261 child, gfx::Rect(10, 430, 60, 70)).IsEmpty()); 1262 EXPECT_RECT_EQ( 1263 gfx::Rect(9, 430, 1, 70), 1264 occlusion.UnoccludedLayerContentRect(child, gfx::Rect(9, 430, 60, 70))); 1265 EXPECT_RECT_EQ(gfx::Rect(), 1266 occlusion.UnoccludedLayerContentRect( 1267 child, gfx::Rect(11, 430, 59, 70))); 1268 EXPECT_RECT_EQ(gfx::Rect(), 1269 occlusion.UnoccludedLayerContentRect( 1270 child, gfx::Rect(10, 431, 60, 69))); 1271 1272 this->LeaveContributingSurface(child, &occlusion); 1273 this->EnterLayer(parent, &occlusion); 1274 1275 EXPECT_EQ(gfx::Rect().ToString(), 1276 occlusion.occlusion_from_outside_target().ToString()); 1277 EXPECT_EQ(gfx::Rect(30, 40, 70, 60).ToString(), 1278 occlusion.occlusion_from_inside_target().ToString()); 1279 1280 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 40, 70, 60))); 1281 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 40, 70, 60))); 1282 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 39, 70, 60))); 1283 1284 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect( 1285 parent, gfx::Rect(30, 40, 70, 60)).IsEmpty()); 1286 EXPECT_RECT_EQ(gfx::Rect(29, 40, 1, 60), 1287 occlusion.UnoccludedLayerContentRect( 1288 parent, gfx::Rect(29, 40, 70, 60))); 1289 EXPECT_RECT_EQ(gfx::Rect(30, 39, 70, 1), 1290 occlusion.UnoccludedLayerContentRect( 1291 parent, gfx::Rect(30, 39, 70, 60))); 1292 EXPECT_RECT_EQ(gfx::Rect(), 1293 occlusion.UnoccludedLayerContentRect( 1294 parent, gfx::Rect(31, 40, 69, 60))); 1295 EXPECT_RECT_EQ(gfx::Rect(), 1296 occlusion.UnoccludedLayerContentRect( 1297 parent, gfx::Rect(30, 41, 70, 59))); 1298 1299 /* Justification for the above occlusion from |layer1| and |layer2|: 1300 1301 +---------------------+ 1302 | |30 Visible region of |layer1|: ///// 1303 | | Visible region of |layer2|: \\\\\ 1304 | +---------------------------------+ 1305 | | |10 | 1306 | +---------------+-----------------+ | 1307 | | |\\\\\\\\\\\\|//| 420 | | 1308 | | |\\\\\\\\\\\\|//|60 | | 1309 | | |\\\\\\\\\\\\|//| | | 1310 +--|--|------------|--+ | | 1311 20|10| 70 | | | 1312 | | | | | 1313 | | | | | 1314 | | | | | 1315 | | | | | 1316 | | | | | 1317 | | | |10| 1318 | +------------|-----------------|--+ 1319 | | 490 | 1320 +---------------+-----------------+ 1321 60 440 1322 */ 1323 } 1324 }; 1325 1326 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestSurfaceWithTwoOpaqueChildren); 1327 1328 template <class Types> 1329 class OcclusionTrackerTestOverlappingSurfaceSiblings 1330 : public OcclusionTrackerTest<Types> { 1331 protected: 1332 explicit OcclusionTrackerTestOverlappingSurfaceSiblings(bool opaque_layers) 1333 : OcclusionTrackerTest<Types>(opaque_layers) {} 1334 void RunMyTest() { 1335 gfx::Transform child_transform; 1336 child_transform.Translate(250.0, 250.0); 1337 child_transform.Rotate(90.0); 1338 child_transform.Translate(-250.0, -250.0); 1339 1340 typename Types::ContentLayerType* parent = this->CreateRoot( 1341 this->identity_matrix, gfx::PointF(), gfx::Size(100, 100)); 1342 parent->SetMasksToBounds(true); 1343 typename Types::LayerType* child1 = this->CreateSurface( 1344 parent, child_transform, gfx::PointF(30.f, 30.f), gfx::Size(10, 10)); 1345 typename Types::LayerType* child2 = this->CreateSurface( 1346 parent, child_transform, gfx::PointF(20.f, 40.f), gfx::Size(10, 10)); 1347 typename Types::ContentLayerType* layer1 = 1348 this->CreateDrawingLayer(child1, 1349 this->identity_matrix, 1350 gfx::PointF(-10.f, -10.f), 1351 gfx::Size(510, 510), 1352 true); 1353 typename Types::ContentLayerType* layer2 = 1354 this->CreateDrawingLayer(child2, 1355 this->identity_matrix, 1356 gfx::PointF(-10.f, -10.f), 1357 gfx::Size(510, 510), 1358 true); 1359 this->CalcDrawEtc(parent); 1360 1361 TestOcclusionTrackerWithClip<typename Types::LayerType, 1362 typename Types::RenderSurfaceType> occlusion( 1363 gfx::Rect(0, 0, 1000, 1000)); 1364 1365 this->VisitLayer(layer2, &occlusion); 1366 this->EnterContributingSurface(child2, &occlusion); 1367 1368 EXPECT_EQ(gfx::Rect().ToString(), 1369 occlusion.occlusion_from_outside_target().ToString()); 1370 EXPECT_EQ(gfx::Rect(-10, 420, 70, 80).ToString(), 1371 occlusion.occlusion_from_inside_target().ToString()); 1372 1373 // There is nothing above child2's surface in the z-order. 1374 EXPECT_RECT_EQ(gfx::Rect(-10, 420, 70, 80), 1375 occlusion.UnoccludedContributingSurfaceContentRect( 1376 child2, false, gfx::Rect(-10, 420, 70, 80))); 1377 1378 this->LeaveContributingSurface(child2, &occlusion); 1379 this->VisitLayer(layer1, &occlusion); 1380 this->EnterContributingSurface(child1, &occlusion); 1381 1382 EXPECT_EQ(gfx::Rect(0, 430, 70, 80).ToString(), 1383 occlusion.occlusion_from_outside_target().ToString()); 1384 EXPECT_EQ(gfx::Rect(-10, 430, 80, 70).ToString(), 1385 occlusion.occlusion_from_inside_target().ToString()); 1386 1387 // child2's contents will occlude child1 below it. 1388 EXPECT_RECT_EQ(gfx::Rect(-10, 430, 10, 70), 1389 occlusion.UnoccludedContributingSurfaceContentRect( 1390 child1, false, gfx::Rect(-10, 430, 80, 70))); 1391 1392 this->LeaveContributingSurface(child1, &occlusion); 1393 this->EnterLayer(parent, &occlusion); 1394 1395 EXPECT_EQ(gfx::Rect().ToString(), 1396 occlusion.occlusion_from_outside_target().ToString()); 1397 EXPECT_EQ(UnionRegions(gfx::Rect(30, 20, 70, 10), gfx::Rect(20, 30, 80, 70)) 1398 .ToString(), 1399 occlusion.occlusion_from_inside_target().ToString()); 1400 1401 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(20, 20, 80, 80))); 1402 1403 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 20, 70, 80))); 1404 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 20, 70, 80))); 1405 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 19, 70, 80))); 1406 1407 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(20, 30, 80, 70))); 1408 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(19, 30, 80, 70))); 1409 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(20, 29, 80, 70))); 1410 1411 /* Justification for the above occlusion: 1412 100 1413 +---------------------+ 1414 | 20 | layer1 1415 | 30+ ---------------------------------+ 1416 100 | 30| | layer2 | 1417 |20+----------------------------------+ | 1418 | | | | | | 1419 | | | | | | 1420 | | | | | | 1421 +--|-|----------------+ | | 1422 | | | | 510 1423 | | | | 1424 | | | | 1425 | | | | 1426 | | | | 1427 | | | | 1428 | | | | 1429 | +--------------------------------|-+ 1430 | | 1431 +----------------------------------+ 1432 510 1433 */ 1434 } 1435 }; 1436 1437 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestOverlappingSurfaceSiblings); 1438 1439 template <class Types> 1440 class OcclusionTrackerTestOverlappingSurfaceSiblingsWithTwoTransforms 1441 : public OcclusionTrackerTest<Types> { 1442 protected: 1443 explicit OcclusionTrackerTestOverlappingSurfaceSiblingsWithTwoTransforms( 1444 bool opaque_layers) 1445 : OcclusionTrackerTest<Types>(opaque_layers) {} 1446 void RunMyTest() { 1447 gfx::Transform child1_transform; 1448 child1_transform.Translate(250.0, 250.0); 1449 child1_transform.Rotate(-90.0); 1450 child1_transform.Translate(-250.0, -250.0); 1451 1452 gfx::Transform child2_transform; 1453 child2_transform.Translate(250.0, 250.0); 1454 child2_transform.Rotate(90.0); 1455 child2_transform.Translate(-250.0, -250.0); 1456 1457 typename Types::ContentLayerType* parent = this->CreateRoot( 1458 this->identity_matrix, gfx::PointF(), gfx::Size(100, 100)); 1459 parent->SetMasksToBounds(true); 1460 typename Types::LayerType* child1 = this->CreateSurface( 1461 parent, child1_transform, gfx::PointF(30.f, 20.f), gfx::Size(10, 10)); 1462 typename Types::LayerType* child2 = 1463 this->CreateDrawingSurface(parent, 1464 child2_transform, 1465 gfx::PointF(20.f, 40.f), 1466 gfx::Size(10, 10), 1467 false); 1468 typename Types::ContentLayerType* layer1 = 1469 this->CreateDrawingLayer(child1, 1470 this->identity_matrix, 1471 gfx::PointF(-10.f, -20.f), 1472 gfx::Size(510, 510), 1473 true); 1474 typename Types::ContentLayerType* layer2 = 1475 this->CreateDrawingLayer(child2, 1476 this->identity_matrix, 1477 gfx::PointF(-10.f, -10.f), 1478 gfx::Size(510, 510), 1479 true); 1480 this->CalcDrawEtc(parent); 1481 1482 TestOcclusionTrackerWithClip<typename Types::LayerType, 1483 typename Types::RenderSurfaceType> occlusion( 1484 gfx::Rect(0, 0, 1000, 1000)); 1485 1486 this->VisitLayer(layer2, &occlusion); 1487 this->EnterLayer(child2, &occlusion); 1488 1489 EXPECT_EQ(gfx::Rect().ToString(), 1490 occlusion.occlusion_from_outside_target().ToString()); 1491 EXPECT_EQ(gfx::Rect(-10, 420, 70, 80).ToString(), 1492 occlusion.occlusion_from_inside_target().ToString()); 1493 1494 this->LeaveLayer(child2, &occlusion); 1495 this->EnterContributingSurface(child2, &occlusion); 1496 1497 // There is nothing above child2's surface in the z-order. 1498 EXPECT_RECT_EQ(gfx::Rect(-10, 420, 70, 80), 1499 occlusion.UnoccludedContributingSurfaceContentRect( 1500 child2, false, gfx::Rect(-10, 420, 70, 80))); 1501 1502 this->LeaveContributingSurface(child2, &occlusion); 1503 this->VisitLayer(layer1, &occlusion); 1504 this->EnterContributingSurface(child1, &occlusion); 1505 1506 EXPECT_EQ(gfx::Rect(420, -10, 70, 80).ToString(), 1507 occlusion.occlusion_from_outside_target().ToString()); 1508 EXPECT_EQ(gfx::Rect(420, -20, 80, 90).ToString(), 1509 occlusion.occlusion_from_inside_target().ToString()); 1510 1511 // child2's contents will occlude child1 below it. 1512 EXPECT_RECT_EQ(gfx::Rect(420, -20, 80, 90), 1513 occlusion.UnoccludedContributingSurfaceContentRect( 1514 child1, false, gfx::Rect(420, -20, 80, 90))); 1515 EXPECT_RECT_EQ(gfx::Rect(490, -10, 10, 80), 1516 occlusion.UnoccludedContributingSurfaceContentRect( 1517 child1, false, gfx::Rect(420, -10, 80, 90))); 1518 EXPECT_RECT_EQ(gfx::Rect(420, -20, 70, 10), 1519 occlusion.UnoccludedContributingSurfaceContentRect( 1520 child1, false, gfx::Rect(420, -20, 70, 90))); 1521 1522 this->LeaveContributingSurface(child1, &occlusion); 1523 this->EnterLayer(parent, &occlusion); 1524 1525 EXPECT_EQ(gfx::Rect().ToString(), 1526 occlusion.occlusion_from_outside_target().ToString()); 1527 EXPECT_EQ(gfx::Rect(10, 20, 90, 80).ToString(), 1528 occlusion.occlusion_from_inside_target().ToString()); 1529 1530 /* Justification for the above occlusion: 1531 100 1532 +---------------------+ 1533 |20 | layer1 1534 10+----------------------------------+ 1535 100 || 30 | layer2 | 1536 |20+----------------------------------+ 1537 || | | | | 1538 || | | | | 1539 || | | | | 1540 +|-|------------------+ | | 1541 | | | | 510 1542 | | 510 | | 1543 | | | | 1544 | | | | 1545 | | | | 1546 | | | | 1547 | | 520 | | 1548 +----------------------------------+ | 1549 | | 1550 +----------------------------------+ 1551 510 1552 */ 1553 } 1554 }; 1555 1556 ALL_OCCLUSIONTRACKER_TEST( 1557 OcclusionTrackerTestOverlappingSurfaceSiblingsWithTwoTransforms); 1558 1559 template <class Types> 1560 class OcclusionTrackerTestFilters : public OcclusionTrackerTest<Types> { 1561 protected: 1562 explicit OcclusionTrackerTestFilters(bool opaque_layers) 1563 : OcclusionTrackerTest<Types>(opaque_layers) {} 1564 void RunMyTest() { 1565 gfx::Transform layer_transform; 1566 layer_transform.Translate(250.0, 250.0); 1567 layer_transform.Rotate(90.0); 1568 layer_transform.Translate(-250.0, -250.0); 1569 1570 typename Types::ContentLayerType* parent = this->CreateRoot( 1571 this->identity_matrix, gfx::PointF(), gfx::Size(100, 100)); 1572 parent->SetMasksToBounds(true); 1573 typename Types::ContentLayerType* blur_layer = 1574 this->CreateDrawingLayer(parent, 1575 layer_transform, 1576 gfx::PointF(30.f, 30.f), 1577 gfx::Size(500, 500), 1578 true); 1579 typename Types::ContentLayerType* opaque_layer = 1580 this->CreateDrawingLayer(parent, 1581 layer_transform, 1582 gfx::PointF(30.f, 30.f), 1583 gfx::Size(500, 500), 1584 true); 1585 typename Types::ContentLayerType* opacity_layer = 1586 this->CreateDrawingLayer(parent, 1587 layer_transform, 1588 gfx::PointF(30.f, 30.f), 1589 gfx::Size(500, 500), 1590 true); 1591 1592 FilterOperations filters; 1593 filters.Append(FilterOperation::CreateBlurFilter(10.f)); 1594 blur_layer->SetFilters(filters); 1595 1596 filters.Clear(); 1597 filters.Append(FilterOperation::CreateGrayscaleFilter(0.5f)); 1598 opaque_layer->SetFilters(filters); 1599 1600 filters.Clear(); 1601 filters.Append(FilterOperation::CreateOpacityFilter(0.5f)); 1602 opacity_layer->SetFilters(filters); 1603 1604 this->CalcDrawEtc(parent); 1605 1606 TestOcclusionTrackerWithClip<typename Types::LayerType, 1607 typename Types::RenderSurfaceType> occlusion( 1608 gfx::Rect(0, 0, 1000, 1000)); 1609 1610 // Opacity layer won't contribute to occlusion. 1611 this->VisitLayer(opacity_layer, &occlusion); 1612 this->EnterContributingSurface(opacity_layer, &occlusion); 1613 1614 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty()); 1615 EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty()); 1616 1617 // And has nothing to contribute to its parent surface. 1618 this->LeaveContributingSurface(opacity_layer, &occlusion); 1619 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty()); 1620 EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty()); 1621 1622 // Opaque layer will contribute to occlusion. 1623 this->VisitLayer(opaque_layer, &occlusion); 1624 this->EnterContributingSurface(opaque_layer, &occlusion); 1625 1626 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty()); 1627 EXPECT_EQ(gfx::Rect(0, 430, 70, 70).ToString(), 1628 occlusion.occlusion_from_inside_target().ToString()); 1629 1630 // And it gets translated to the parent surface. 1631 this->LeaveContributingSurface(opaque_layer, &occlusion); 1632 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty()); 1633 EXPECT_EQ(gfx::Rect(30, 30, 70, 70).ToString(), 1634 occlusion.occlusion_from_inside_target().ToString()); 1635 1636 // The blur layer needs to throw away any occlusion from outside its 1637 // subtree. 1638 this->EnterLayer(blur_layer, &occlusion); 1639 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty()); 1640 EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty()); 1641 1642 // And it won't contribute to occlusion. 1643 this->LeaveLayer(blur_layer, &occlusion); 1644 this->EnterContributingSurface(blur_layer, &occlusion); 1645 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty()); 1646 EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty()); 1647 1648 // But the opaque layer's occlusion is preserved on the parent. 1649 this->LeaveContributingSurface(blur_layer, &occlusion); 1650 this->EnterLayer(parent, &occlusion); 1651 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty()); 1652 EXPECT_EQ(gfx::Rect(30, 30, 70, 70).ToString(), 1653 occlusion.occlusion_from_inside_target().ToString()); 1654 } 1655 }; 1656 1657 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestFilters); 1658 1659 template <class Types> 1660 class OcclusionTrackerTestReplicaDoesOcclude 1661 : public OcclusionTrackerTest<Types> { 1662 protected: 1663 explicit OcclusionTrackerTestReplicaDoesOcclude(bool opaque_layers) 1664 : OcclusionTrackerTest<Types>(opaque_layers) {} 1665 void RunMyTest() { 1666 typename Types::ContentLayerType* parent = this->CreateRoot( 1667 this->identity_matrix, gfx::PointF(), gfx::Size(100, 200)); 1668 typename Types::LayerType* surface = 1669 this->CreateDrawingSurface(parent, 1670 this->identity_matrix, 1671 gfx::PointF(0.f, 100.f), 1672 gfx::Size(50, 50), 1673 true); 1674 this->CreateReplicaLayer( 1675 surface, this->identity_matrix, gfx::PointF(50.f, 50.f), gfx::Size()); 1676 this->CalcDrawEtc(parent); 1677 1678 TestOcclusionTrackerWithClip<typename Types::LayerType, 1679 typename Types::RenderSurfaceType> occlusion( 1680 gfx::Rect(0, 0, 1000, 1000)); 1681 1682 this->VisitLayer(surface, &occlusion); 1683 1684 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(), 1685 occlusion.occlusion_from_inside_target().ToString()); 1686 1687 this->VisitContributingSurface(surface, &occlusion); 1688 this->EnterLayer(parent, &occlusion); 1689 1690 // The surface and replica should both be occluding the parent. 1691 EXPECT_EQ( 1692 UnionRegions(gfx::Rect(0, 100, 50, 50), 1693 gfx::Rect(50, 150, 50, 50)).ToString(), 1694 occlusion.occlusion_from_inside_target().ToString()); 1695 } 1696 }; 1697 1698 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestReplicaDoesOcclude); 1699 1700 template <class Types> 1701 class OcclusionTrackerTestReplicaWithClipping 1702 : public OcclusionTrackerTest<Types> { 1703 protected: 1704 explicit OcclusionTrackerTestReplicaWithClipping(bool opaque_layers) 1705 : OcclusionTrackerTest<Types>(opaque_layers) {} 1706 void RunMyTest() { 1707 typename Types::ContentLayerType* parent = this->CreateRoot( 1708 this->identity_matrix, gfx::PointF(), gfx::Size(100, 170)); 1709 parent->SetMasksToBounds(true); 1710 typename Types::LayerType* surface = 1711 this->CreateDrawingSurface(parent, 1712 this->identity_matrix, 1713 gfx::PointF(0.f, 100.f), 1714 gfx::Size(50, 50), 1715 true); 1716 this->CreateReplicaLayer( 1717 surface, this->identity_matrix, gfx::PointF(50.f, 50.f), gfx::Size()); 1718 this->CalcDrawEtc(parent); 1719 1720 TestOcclusionTrackerWithClip<typename Types::LayerType, 1721 typename Types::RenderSurfaceType> occlusion( 1722 gfx::Rect(0, 0, 1000, 1000)); 1723 1724 this->VisitLayer(surface, &occlusion); 1725 1726 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(), 1727 occlusion.occlusion_from_inside_target().ToString()); 1728 1729 this->VisitContributingSurface(surface, &occlusion); 1730 this->EnterLayer(parent, &occlusion); 1731 1732 // The surface and replica should both be occluding the parent. 1733 EXPECT_EQ( 1734 UnionRegions(gfx::Rect(0, 100, 50, 50), 1735 gfx::Rect(50, 150, 50, 20)).ToString(), 1736 occlusion.occlusion_from_inside_target().ToString()); 1737 } 1738 }; 1739 1740 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestReplicaWithClipping); 1741 1742 template <class Types> 1743 class OcclusionTrackerTestReplicaWithMask : public OcclusionTrackerTest<Types> { 1744 protected: 1745 explicit OcclusionTrackerTestReplicaWithMask(bool opaque_layers) 1746 : OcclusionTrackerTest<Types>(opaque_layers) {} 1747 void RunMyTest() { 1748 typename Types::ContentLayerType* parent = this->CreateRoot( 1749 this->identity_matrix, gfx::PointF(), gfx::Size(100, 200)); 1750 typename Types::LayerType* surface = 1751 this->CreateDrawingSurface(parent, 1752 this->identity_matrix, 1753 gfx::PointF(0.f, 100.f), 1754 gfx::Size(50, 50), 1755 true); 1756 typename Types::LayerType* replica = this->CreateReplicaLayer( 1757 surface, this->identity_matrix, gfx::PointF(50.f, 50.f), gfx::Size()); 1758 this->CreateMaskLayer(replica, gfx::Size(10, 10)); 1759 this->CalcDrawEtc(parent); 1760 1761 TestOcclusionTrackerWithClip<typename Types::LayerType, 1762 typename Types::RenderSurfaceType> occlusion( 1763 gfx::Rect(0, 0, 1000, 1000)); 1764 1765 this->VisitLayer(surface, &occlusion); 1766 1767 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(), 1768 occlusion.occlusion_from_inside_target().ToString()); 1769 1770 this->VisitContributingSurface(surface, &occlusion); 1771 this->EnterLayer(parent, &occlusion); 1772 1773 // The replica should not be occluding the parent, since it has a mask 1774 // applied to it. 1775 EXPECT_EQ(gfx::Rect(0, 100, 50, 50).ToString(), 1776 occlusion.occlusion_from_inside_target().ToString()); 1777 } 1778 }; 1779 1780 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestReplicaWithMask); 1781 1782 template <class Types> 1783 class OcclusionTrackerTestOpaqueContentsRegionEmpty 1784 : public OcclusionTrackerTest<Types> { 1785 protected: 1786 explicit OcclusionTrackerTestOpaqueContentsRegionEmpty(bool opaque_layers) 1787 : OcclusionTrackerTest<Types>(opaque_layers) {} 1788 void RunMyTest() { 1789 typename Types::ContentLayerType* parent = this->CreateRoot( 1790 this->identity_matrix, gfx::PointF(), gfx::Size(300, 300)); 1791 typename Types::ContentLayerType* layer = 1792 this->CreateDrawingSurface(parent, 1793 this->identity_matrix, 1794 gfx::PointF(), 1795 gfx::Size(200, 200), 1796 false); 1797 this->CalcDrawEtc(parent); 1798 1799 TestOcclusionTrackerWithClip<typename Types::LayerType, 1800 typename Types::RenderSurfaceType> occlusion( 1801 gfx::Rect(0, 0, 1000, 1000)); 1802 this->EnterLayer(layer, &occlusion); 1803 1804 EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(0, 0, 100, 100))); 1805 EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(100, 0, 100, 100))); 1806 EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(0, 100, 100, 100))); 1807 EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(100, 100, 100, 100))); 1808 1809 this->LeaveLayer(layer, &occlusion); 1810 this->VisitContributingSurface(layer, &occlusion); 1811 this->EnterLayer(parent, &occlusion); 1812 1813 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty()); 1814 } 1815 }; 1816 1817 MAIN_AND_IMPL_THREAD_TEST(OcclusionTrackerTestOpaqueContentsRegionEmpty); 1818 1819 template <class Types> 1820 class OcclusionTrackerTestOpaqueContentsRegionNonEmpty 1821 : public OcclusionTrackerTest<Types> { 1822 protected: 1823 explicit OcclusionTrackerTestOpaqueContentsRegionNonEmpty(bool opaque_layers) 1824 : OcclusionTrackerTest<Types>(opaque_layers) {} 1825 void RunMyTest() { 1826 typename Types::ContentLayerType* parent = this->CreateRoot( 1827 this->identity_matrix, gfx::PointF(), gfx::Size(300, 300)); 1828 typename Types::ContentLayerType* layer = 1829 this->CreateDrawingLayer(parent, 1830 this->identity_matrix, 1831 gfx::PointF(100.f, 100.f), 1832 gfx::Size(200, 200), 1833 false); 1834 this->CalcDrawEtc(parent); 1835 { 1836 TestOcclusionTrackerWithClip<typename Types::LayerType, 1837 typename Types::RenderSurfaceType> occlusion( 1838 gfx::Rect(0, 0, 1000, 1000)); 1839 layer->SetOpaqueContentsRect(gfx::Rect(0, 0, 100, 100)); 1840 1841 this->ResetLayerIterator(); 1842 this->VisitLayer(layer, &occlusion); 1843 this->EnterLayer(parent, &occlusion); 1844 1845 EXPECT_EQ(gfx::Rect(100, 100, 100, 100).ToString(), 1846 occlusion.occlusion_from_inside_target().ToString()); 1847 1848 EXPECT_FALSE( 1849 occlusion.OccludedLayer(parent, gfx::Rect(0, 100, 100, 100))); 1850 EXPECT_TRUE( 1851 occlusion.OccludedLayer(parent, gfx::Rect(100, 100, 100, 100))); 1852 EXPECT_FALSE( 1853 occlusion.OccludedLayer(parent, gfx::Rect(200, 200, 100, 100))); 1854 } 1855 { 1856 TestOcclusionTrackerWithClip<typename Types::LayerType, 1857 typename Types::RenderSurfaceType> occlusion( 1858 gfx::Rect(0, 0, 1000, 1000)); 1859 layer->SetOpaqueContentsRect(gfx::Rect(20, 20, 180, 180)); 1860 1861 this->ResetLayerIterator(); 1862 this->VisitLayer(layer, &occlusion); 1863 this->EnterLayer(parent, &occlusion); 1864 1865 EXPECT_EQ(gfx::Rect(120, 120, 180, 180).ToString(), 1866 occlusion.occlusion_from_inside_target().ToString()); 1867 1868 EXPECT_FALSE( 1869 occlusion.OccludedLayer(parent, gfx::Rect(0, 100, 100, 100))); 1870 EXPECT_FALSE( 1871 occlusion.OccludedLayer(parent, gfx::Rect(100, 100, 100, 100))); 1872 EXPECT_TRUE( 1873 occlusion.OccludedLayer(parent, gfx::Rect(200, 200, 100, 100))); 1874 } 1875 { 1876 TestOcclusionTrackerWithClip<typename Types::LayerType, 1877 typename Types::RenderSurfaceType> occlusion( 1878 gfx::Rect(0, 0, 1000, 1000)); 1879 layer->SetOpaqueContentsRect(gfx::Rect(150, 150, 100, 100)); 1880 1881 this->ResetLayerIterator(); 1882 this->VisitLayer(layer, &occlusion); 1883 this->EnterLayer(parent, &occlusion); 1884 1885 EXPECT_EQ(gfx::Rect(250, 250, 50, 50).ToString(), 1886 occlusion.occlusion_from_inside_target().ToString()); 1887 1888 EXPECT_FALSE( 1889 occlusion.OccludedLayer(parent, gfx::Rect(0, 100, 100, 100))); 1890 EXPECT_FALSE( 1891 occlusion.OccludedLayer(parent, gfx::Rect(100, 100, 100, 100))); 1892 EXPECT_FALSE( 1893 occlusion.OccludedLayer(parent, gfx::Rect(200, 200, 100, 100))); 1894 } 1895 } 1896 }; 1897 1898 MAIN_AND_IMPL_THREAD_TEST(OcclusionTrackerTestOpaqueContentsRegionNonEmpty); 1899 1900 template <class Types> 1901 class OcclusionTrackerTest3dTransform : public OcclusionTrackerTest<Types> { 1902 protected: 1903 explicit OcclusionTrackerTest3dTransform(bool opaque_layers) 1904 : OcclusionTrackerTest<Types>(opaque_layers) {} 1905 void RunMyTest() { 1906 gfx::Transform transform; 1907 transform.RotateAboutYAxis(30.0); 1908 1909 typename Types::ContentLayerType* parent = this->CreateRoot( 1910 this->identity_matrix, gfx::PointF(), gfx::Size(300, 300)); 1911 typename Types::LayerType* container = this->CreateLayer( 1912 parent, this->identity_matrix, gfx::PointF(), gfx::Size(300, 300)); 1913 typename Types::ContentLayerType* layer = 1914 this->CreateDrawingLayer(container, 1915 transform, 1916 gfx::PointF(100.f, 100.f), 1917 gfx::Size(200, 200), 1918 true); 1919 this->CalcDrawEtc(parent); 1920 1921 TestOcclusionTrackerWithClip<typename Types::LayerType, 1922 typename Types::RenderSurfaceType> occlusion( 1923 gfx::Rect(0, 0, 1000, 1000)); 1924 this->EnterLayer(layer, &occlusion); 1925 1926 // The layer is rotated in 3d but without preserving 3d, so it only gets 1927 // resized. 1928 EXPECT_RECT_EQ( 1929 gfx::Rect(0, 0, 200, 200), 1930 occlusion.UnoccludedLayerContentRect(layer, gfx::Rect(0, 0, 200, 200))); 1931 } 1932 }; 1933 1934 MAIN_AND_IMPL_THREAD_TEST(OcclusionTrackerTest3dTransform); 1935 1936 template <class Types> 1937 class OcclusionTrackerTestUnsorted3dLayers 1938 : public OcclusionTrackerTest<Types> { 1939 protected: 1940 explicit OcclusionTrackerTestUnsorted3dLayers(bool opaque_layers) 1941 : OcclusionTrackerTest<Types>(opaque_layers) {} 1942 void RunMyTest() { 1943 // Currently, The main thread layer iterator does not iterate over 3d items 1944 // in sorted order, because layer sorting is not performed on the main 1945 // thread. Because of this, the occlusion tracker cannot assume that a 3d 1946 // layer occludes other layers that have not yet been iterated over. For 1947 // now, the expected behavior is that a 3d layer simply does not add any 1948 // occlusion to the occlusion tracker. 1949 1950 gfx::Transform translation_to_front; 1951 translation_to_front.Translate3d(0.0, 0.0, -10.0); 1952 gfx::Transform translation_to_back; 1953 translation_to_front.Translate3d(0.0, 0.0, -100.0); 1954 1955 typename Types::ContentLayerType* parent = this->CreateRoot( 1956 this->identity_matrix, gfx::PointF(), gfx::Size(300, 300)); 1957 typename Types::ContentLayerType* child1 = this->CreateDrawingLayer( 1958 parent, translation_to_back, gfx::PointF(), gfx::Size(100, 100), true); 1959 typename Types::ContentLayerType* child2 = 1960 this->CreateDrawingLayer(parent, 1961 translation_to_front, 1962 gfx::PointF(50.f, 50.f), 1963 gfx::Size(100, 100), 1964 true); 1965 parent->SetPreserves3d(true); 1966 1967 this->CalcDrawEtc(parent); 1968 1969 TestOcclusionTrackerWithClip<typename Types::LayerType, 1970 typename Types::RenderSurfaceType> occlusion( 1971 gfx::Rect(0, 0, 1000, 1000)); 1972 this->VisitLayer(child2, &occlusion); 1973 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty()); 1974 EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty()); 1975 1976 this->VisitLayer(child1, &occlusion); 1977 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty()); 1978 EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty()); 1979 } 1980 }; 1981 1982 // This test will have different layer ordering on the impl thread; the test 1983 // will only work on the main thread. 1984 MAIN_THREAD_TEST(OcclusionTrackerTestUnsorted3dLayers); 1985 1986 template <class Types> 1987 class OcclusionTrackerTestPerspectiveTransform 1988 : public OcclusionTrackerTest<Types> { 1989 protected: 1990 explicit OcclusionTrackerTestPerspectiveTransform(bool opaque_layers) 1991 : OcclusionTrackerTest<Types>(opaque_layers) {} 1992 void RunMyTest() { 1993 gfx::Transform transform; 1994 transform.Translate(150.0, 150.0); 1995 transform.ApplyPerspectiveDepth(400.0); 1996 transform.RotateAboutXAxis(-30.0); 1997 transform.Translate(-150.0, -150.0); 1998 1999 typename Types::ContentLayerType* parent = this->CreateRoot( 2000 this->identity_matrix, gfx::PointF(), gfx::Size(300, 300)); 2001 typename Types::LayerType* container = this->CreateLayer( 2002 parent, this->identity_matrix, gfx::PointF(), gfx::Size(300, 300)); 2003 typename Types::ContentLayerType* layer = 2004 this->CreateDrawingLayer(container, 2005 transform, 2006 gfx::PointF(100.f, 100.f), 2007 gfx::Size(200, 200), 2008 true); 2009 container->SetPreserves3d(true); 2010 layer->SetPreserves3d(true); 2011 this->CalcDrawEtc(parent); 2012 2013 TestOcclusionTrackerWithClip<typename Types::LayerType, 2014 typename Types::RenderSurfaceType> occlusion( 2015 gfx::Rect(0, 0, 1000, 1000)); 2016 this->EnterLayer(layer, &occlusion); 2017 2018 EXPECT_RECT_EQ( 2019 gfx::Rect(0, 0, 200, 200), 2020 occlusion.UnoccludedLayerContentRect(layer, gfx::Rect(0, 0, 200, 200))); 2021 } 2022 }; 2023 2024 // This test requires accumulating occlusion of 3d layers, which are skipped by 2025 // the occlusion tracker on the main thread. So this test should run on the impl 2026 // thread. 2027 IMPL_THREAD_TEST(OcclusionTrackerTestPerspectiveTransform); 2028 2029 template <class Types> 2030 class OcclusionTrackerTestPerspectiveTransformBehindCamera 2031 : public OcclusionTrackerTest<Types> { 2032 protected: 2033 explicit OcclusionTrackerTestPerspectiveTransformBehindCamera( 2034 bool opaque_layers) 2035 : OcclusionTrackerTest<Types>(opaque_layers) {} 2036 void RunMyTest() { 2037 // This test is based on the platform/chromium/compositing/3d-corners.html 2038 // layout test. 2039 gfx::Transform transform; 2040 transform.Translate(250.0, 50.0); 2041 transform.ApplyPerspectiveDepth(10.0); 2042 transform.Translate(-250.0, -50.0); 2043 transform.Translate(250.0, 50.0); 2044 transform.RotateAboutXAxis(-167.0); 2045 transform.Translate(-250.0, -50.0); 2046 2047 typename Types::ContentLayerType* parent = this->CreateRoot( 2048 this->identity_matrix, gfx::PointF(), gfx::Size(500, 100)); 2049 typename Types::LayerType* container = this->CreateLayer( 2050 parent, this->identity_matrix, gfx::PointF(), gfx::Size(500, 500)); 2051 typename Types::ContentLayerType* layer = this->CreateDrawingLayer( 2052 container, transform, gfx::PointF(), gfx::Size(500, 500), true); 2053 container->SetPreserves3d(true); 2054 layer->SetPreserves3d(true); 2055 this->CalcDrawEtc(parent); 2056 2057 TestOcclusionTrackerWithClip<typename Types::LayerType, 2058 typename Types::RenderSurfaceType> occlusion( 2059 gfx::Rect(0, 0, 1000, 1000)); 2060 this->EnterLayer(layer, &occlusion); 2061 2062 // The bottom 11 pixel rows of this layer remain visible inside the 2063 // container, after translation to the target surface. When translated back, 2064 // this will include many more pixels but must include at least the bottom 2065 // 11 rows. 2066 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect( 2067 layer, gfx::Rect(0, 26, 500, 474)). 2068 Contains(gfx::Rect(0, 489, 500, 11))); 2069 } 2070 }; 2071 2072 // This test requires accumulating occlusion of 3d layers, which are skipped by 2073 // the occlusion tracker on the main thread. So this test should run on the impl 2074 // thread. 2075 IMPL_THREAD_TEST(OcclusionTrackerTestPerspectiveTransformBehindCamera); 2076 2077 template <class Types> 2078 class OcclusionTrackerTestLayerBehindCameraDoesNotOcclude 2079 : public OcclusionTrackerTest<Types> { 2080 protected: 2081 explicit OcclusionTrackerTestLayerBehindCameraDoesNotOcclude( 2082 bool opaque_layers) 2083 : OcclusionTrackerTest<Types>(opaque_layers) {} 2084 void RunMyTest() { 2085 gfx::Transform transform; 2086 transform.Translate(50.0, 50.0); 2087 transform.ApplyPerspectiveDepth(100.0); 2088 transform.Translate3d(0.0, 0.0, 110.0); 2089 transform.Translate(-50.0, -50.0); 2090 2091 typename Types::ContentLayerType* parent = this->CreateRoot( 2092 this->identity_matrix, gfx::PointF(), gfx::Size(100, 100)); 2093 typename Types::ContentLayerType* layer = this->CreateDrawingLayer( 2094 parent, transform, gfx::PointF(), gfx::Size(100, 100), true); 2095 parent->SetPreserves3d(true); 2096 layer->SetPreserves3d(true); 2097 this->CalcDrawEtc(parent); 2098 2099 TestOcclusionTrackerWithClip<typename Types::LayerType, 2100 typename Types::RenderSurfaceType> occlusion( 2101 gfx::Rect(0, 0, 1000, 1000)); 2102 2103 // The |layer| is entirely behind the camera and should not occlude. 2104 this->VisitLayer(layer, &occlusion); 2105 this->EnterLayer(parent, &occlusion); 2106 EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty()); 2107 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty()); 2108 } 2109 }; 2110 2111 // This test requires accumulating occlusion of 3d layers, which are skipped by 2112 // the occlusion tracker on the main thread. So this test should run on the impl 2113 // thread. 2114 IMPL_THREAD_TEST(OcclusionTrackerTestLayerBehindCameraDoesNotOcclude); 2115 2116 template <class Types> 2117 class OcclusionTrackerTestLargePixelsOccludeInsideClipRect 2118 : public OcclusionTrackerTest<Types> { 2119 protected: 2120 explicit OcclusionTrackerTestLargePixelsOccludeInsideClipRect( 2121 bool opaque_layers) 2122 : OcclusionTrackerTest<Types>(opaque_layers) {} 2123 void RunMyTest() { 2124 gfx::Transform transform; 2125 transform.Translate(50.0, 50.0); 2126 transform.ApplyPerspectiveDepth(100.0); 2127 transform.Translate3d(0.0, 0.0, 99.0); 2128 transform.Translate(-50.0, -50.0); 2129 2130 typename Types::ContentLayerType* parent = this->CreateRoot( 2131 this->identity_matrix, gfx::PointF(), gfx::Size(100, 100)); 2132 parent->SetMasksToBounds(true); 2133 typename Types::ContentLayerType* layer = this->CreateDrawingLayer( 2134 parent, transform, gfx::PointF(), gfx::Size(100, 100), true); 2135 parent->SetPreserves3d(true); 2136 layer->SetPreserves3d(true); 2137 this->CalcDrawEtc(parent); 2138 2139 TestOcclusionTrackerWithClip<typename Types::LayerType, 2140 typename Types::RenderSurfaceType> occlusion( 2141 gfx::Rect(0, 0, 1000, 1000)); 2142 2143 // This is very close to the camera, so pixels in its visible_content_rect() 2144 // will actually go outside of the layer's clip rect. Ensure that those 2145 // pixels don't occlude things outside the clip rect. 2146 this->VisitLayer(layer, &occlusion); 2147 this->EnterLayer(parent, &occlusion); 2148 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), 2149 occlusion.occlusion_from_inside_target().ToString()); 2150 EXPECT_EQ(gfx::Rect().ToString(), 2151 occlusion.occlusion_from_outside_target().ToString()); 2152 } 2153 }; 2154 2155 // This test requires accumulating occlusion of 3d layers, which are skipped by 2156 // the occlusion tracker on the main thread. So this test should run on the impl 2157 // thread. 2158 IMPL_THREAD_TEST(OcclusionTrackerTestLargePixelsOccludeInsideClipRect); 2159 2160 template <class Types> 2161 class OcclusionTrackerTestAnimationOpacity1OnMainThread 2162 : public OcclusionTrackerTest<Types> { 2163 protected: 2164 explicit OcclusionTrackerTestAnimationOpacity1OnMainThread(bool opaque_layers) 2165 : OcclusionTrackerTest<Types>(opaque_layers) {} 2166 void RunMyTest() { 2167 // parent 2168 // +--layer 2169 // +--surface 2170 // | +--surface_child 2171 // | +--surface_child2 2172 // +--parent2 2173 // +--topmost 2174 2175 typename Types::ContentLayerType* parent = this->CreateRoot( 2176 this->identity_matrix, gfx::PointF(), gfx::Size(300, 300)); 2177 typename Types::ContentLayerType* layer = 2178 this->CreateDrawingLayer(parent, 2179 this->identity_matrix, 2180 gfx::PointF(), 2181 gfx::Size(300, 300), 2182 true); 2183 typename Types::ContentLayerType* surface = 2184 this->CreateDrawingSurface(parent, 2185 this->identity_matrix, 2186 gfx::PointF(), 2187 gfx::Size(300, 300), 2188 true); 2189 typename Types::ContentLayerType* surface_child = 2190 this->CreateDrawingLayer(surface, 2191 this->identity_matrix, 2192 gfx::PointF(), 2193 gfx::Size(200, 300), 2194 true); 2195 typename Types::ContentLayerType* surface_child2 = 2196 this->CreateDrawingLayer(surface, 2197 this->identity_matrix, 2198 gfx::PointF(), 2199 gfx::Size(100, 300), 2200 true); 2201 typename Types::ContentLayerType* parent2 = 2202 this->CreateDrawingLayer(parent, 2203 this->identity_matrix, 2204 gfx::PointF(), 2205 gfx::Size(300, 300), 2206 false); 2207 typename Types::ContentLayerType* topmost = 2208 this->CreateDrawingLayer(parent, 2209 this->identity_matrix, 2210 gfx::PointF(250.f, 0.f), 2211 gfx::Size(50, 300), 2212 true); 2213 2214 AddOpacityTransitionToController( 2215 layer->layer_animation_controller(), 10.0, 0.f, 1.f, false); 2216 AddOpacityTransitionToController( 2217 surface->layer_animation_controller(), 10.0, 0.f, 1.f, false); 2218 this->CalcDrawEtc(parent); 2219 2220 EXPECT_TRUE(layer->draw_opacity_is_animating()); 2221 EXPECT_FALSE(surface->draw_opacity_is_animating()); 2222 EXPECT_TRUE(surface->render_surface()->draw_opacity_is_animating()); 2223 2224 TestOcclusionTrackerWithClip<typename Types::LayerType, 2225 typename Types::RenderSurfaceType> occlusion( 2226 gfx::Rect(0, 0, 1000, 1000)); 2227 2228 this->VisitLayer(topmost, &occlusion); 2229 this->EnterLayer(parent2, &occlusion); 2230 // This occlusion will affect all surfaces. 2231 EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(), 2232 occlusion.occlusion_from_inside_target().ToString()); 2233 EXPECT_EQ(gfx::Rect().ToString(), 2234 occlusion.occlusion_from_outside_target().ToString()); 2235 EXPECT_EQ(gfx::Rect(0, 0, 250, 300).ToString(), 2236 occlusion.UnoccludedLayerContentRect( 2237 parent2, gfx::Rect(0, 0, 300, 300)).ToString()); 2238 this->LeaveLayer(parent2, &occlusion); 2239 2240 this->VisitLayer(surface_child2, &occlusion); 2241 this->EnterLayer(surface_child, &occlusion); 2242 EXPECT_EQ(gfx::Rect(0, 0, 100, 300).ToString(), 2243 occlusion.occlusion_from_inside_target().ToString()); 2244 EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(), 2245 occlusion.occlusion_from_outside_target().ToString()); 2246 EXPECT_RECT_EQ(gfx::Rect(100, 0, 100, 300), 2247 occlusion.UnoccludedLayerContentRect( 2248 surface_child, gfx::Rect(0, 0, 200, 300))); 2249 this->LeaveLayer(surface_child, &occlusion); 2250 this->EnterLayer(surface, &occlusion); 2251 EXPECT_EQ(gfx::Rect(0, 0, 200, 300).ToString(), 2252 occlusion.occlusion_from_inside_target().ToString()); 2253 EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(), 2254 occlusion.occlusion_from_outside_target().ToString()); 2255 EXPECT_RECT_EQ(gfx::Rect(200, 0, 50, 300), 2256 occlusion.UnoccludedLayerContentRect( 2257 surface, gfx::Rect(0, 0, 300, 300))); 2258 this->LeaveLayer(surface, &occlusion); 2259 2260 this->EnterContributingSurface(surface, &occlusion); 2261 // Occlusion within the surface is lost when leaving the animating surface. 2262 EXPECT_EQ(gfx::Rect().ToString(), 2263 occlusion.occlusion_from_inside_target().ToString()); 2264 EXPECT_EQ(gfx::Rect().ToString(), 2265 occlusion.occlusion_from_outside_target().ToString()); 2266 EXPECT_RECT_EQ(gfx::Rect(0, 0, 250, 300), 2267 occlusion.UnoccludedContributingSurfaceContentRect( 2268 surface, false, gfx::Rect(0, 0, 300, 300))); 2269 this->LeaveContributingSurface(surface, &occlusion); 2270 2271 // Occlusion from outside the animating surface still exists. 2272 EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(), 2273 occlusion.occlusion_from_inside_target().ToString()); 2274 EXPECT_EQ(gfx::Rect().ToString(), 2275 occlusion.occlusion_from_outside_target().ToString()); 2276 2277 this->VisitLayer(layer, &occlusion); 2278 this->EnterLayer(parent, &occlusion); 2279 2280 // Occlusion is not added for the animating |layer|. 2281 EXPECT_RECT_EQ(gfx::Rect(0, 0, 250, 300), 2282 occlusion.UnoccludedLayerContentRect( 2283 parent, gfx::Rect(0, 0, 300, 300))); 2284 } 2285 }; 2286 2287 MAIN_THREAD_TEST(OcclusionTrackerTestAnimationOpacity1OnMainThread); 2288 2289 template <class Types> 2290 class OcclusionTrackerTestAnimationOpacity0OnMainThread 2291 : public OcclusionTrackerTest<Types> { 2292 protected: 2293 explicit OcclusionTrackerTestAnimationOpacity0OnMainThread(bool opaque_layers) 2294 : OcclusionTrackerTest<Types>(opaque_layers) {} 2295 void RunMyTest() { 2296 typename Types::ContentLayerType* parent = this->CreateRoot( 2297 this->identity_matrix, gfx::PointF(), gfx::Size(300, 300)); 2298 typename Types::ContentLayerType* layer = 2299 this->CreateDrawingLayer(parent, 2300 this->identity_matrix, 2301 gfx::PointF(), 2302 gfx::Size(300, 300), 2303 true); 2304 typename Types::ContentLayerType* surface = 2305 this->CreateDrawingSurface(parent, 2306 this->identity_matrix, 2307 gfx::PointF(), 2308 gfx::Size(300, 300), 2309 true); 2310 typename Types::ContentLayerType* surface_child = 2311 this->CreateDrawingLayer(surface, 2312 this->identity_matrix, 2313 gfx::PointF(), 2314 gfx::Size(200, 300), 2315 true); 2316 typename Types::ContentLayerType* surface_child2 = 2317 this->CreateDrawingLayer(surface, 2318 this->identity_matrix, 2319 gfx::PointF(), 2320 gfx::Size(100, 300), 2321 true); 2322 typename Types::ContentLayerType* parent2 = 2323 this->CreateDrawingLayer(parent, 2324 this->identity_matrix, 2325 gfx::PointF(), 2326 gfx::Size(300, 300), 2327 false); 2328 typename Types::ContentLayerType* topmost = 2329 this->CreateDrawingLayer(parent, 2330 this->identity_matrix, 2331 gfx::PointF(250.f, 0.f), 2332 gfx::Size(50, 300), 2333 true); 2334 2335 AddOpacityTransitionToController( 2336 layer->layer_animation_controller(), 10.0, 1.f, 0.f, false); 2337 AddOpacityTransitionToController( 2338 surface->layer_animation_controller(), 10.0, 1.f, 0.f, false); 2339 this->CalcDrawEtc(parent); 2340 2341 EXPECT_TRUE(layer->draw_opacity_is_animating()); 2342 EXPECT_FALSE(surface->draw_opacity_is_animating()); 2343 EXPECT_TRUE(surface->render_surface()->draw_opacity_is_animating()); 2344 2345 TestOcclusionTrackerWithClip<typename Types::LayerType, 2346 typename Types::RenderSurfaceType> occlusion( 2347 gfx::Rect(0, 0, 1000, 1000)); 2348 2349 this->VisitLayer(topmost, &occlusion); 2350 this->EnterLayer(parent2, &occlusion); 2351 // This occlusion will affect all surfaces. 2352 EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(), 2353 occlusion.occlusion_from_inside_target().ToString()); 2354 EXPECT_EQ(gfx::Rect().ToString(), 2355 occlusion.occlusion_from_outside_target().ToString()); 2356 EXPECT_RECT_EQ(gfx::Rect(0, 0, 250, 300), 2357 occlusion.UnoccludedLayerContentRect( 2358 parent, gfx::Rect(0, 0, 300, 300))); 2359 this->LeaveLayer(parent2, &occlusion); 2360 2361 this->VisitLayer(surface_child2, &occlusion); 2362 this->EnterLayer(surface_child, &occlusion); 2363 EXPECT_EQ(gfx::Rect(0, 0, 100, 300).ToString(), 2364 occlusion.occlusion_from_inside_target().ToString()); 2365 EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(), 2366 occlusion.occlusion_from_outside_target().ToString()); 2367 EXPECT_RECT_EQ(gfx::Rect(100, 0, 100, 300), 2368 occlusion.UnoccludedLayerContentRect( 2369 surface_child, gfx::Rect(0, 0, 200, 300))); 2370 this->LeaveLayer(surface_child, &occlusion); 2371 this->EnterLayer(surface, &occlusion); 2372 EXPECT_EQ(gfx::Rect(0, 0, 200, 300).ToString(), 2373 occlusion.occlusion_from_inside_target().ToString()); 2374 EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(), 2375 occlusion.occlusion_from_outside_target().ToString()); 2376 EXPECT_RECT_EQ(gfx::Rect(200, 0, 50, 300), 2377 occlusion.UnoccludedLayerContentRect( 2378 surface, gfx::Rect(0, 0, 300, 300))); 2379 this->LeaveLayer(surface, &occlusion); 2380 2381 this->EnterContributingSurface(surface, &occlusion); 2382 // Occlusion within the surface is lost when leaving the animating surface. 2383 EXPECT_EQ(gfx::Rect().ToString(), 2384 occlusion.occlusion_from_inside_target().ToString()); 2385 EXPECT_EQ(gfx::Rect().ToString(), 2386 occlusion.occlusion_from_outside_target().ToString()); 2387 EXPECT_RECT_EQ(gfx::Rect(0, 0, 250, 300), 2388 occlusion.UnoccludedContributingSurfaceContentRect( 2389 surface, false, gfx::Rect(0, 0, 300, 300))); 2390 this->LeaveContributingSurface(surface, &occlusion); 2391 2392 // Occlusion from outside the animating surface still exists. 2393 EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(), 2394 occlusion.occlusion_from_inside_target().ToString()); 2395 EXPECT_EQ(gfx::Rect().ToString(), 2396 occlusion.occlusion_from_outside_target().ToString()); 2397 2398 this->VisitLayer(layer, &occlusion); 2399 this->EnterLayer(parent, &occlusion); 2400 2401 // Occlusion is not added for the animating |layer|. 2402 EXPECT_RECT_EQ(gfx::Rect(0, 0, 250, 300), 2403 occlusion.UnoccludedLayerContentRect( 2404 parent, gfx::Rect(0, 0, 300, 300))); 2405 } 2406 }; 2407 2408 MAIN_THREAD_TEST(OcclusionTrackerTestAnimationOpacity0OnMainThread); 2409 2410 template <class Types> 2411 class OcclusionTrackerTestAnimationTranslateOnMainThread 2412 : public OcclusionTrackerTest<Types> { 2413 protected: 2414 explicit OcclusionTrackerTestAnimationTranslateOnMainThread( 2415 bool opaque_layers) 2416 : OcclusionTrackerTest<Types>(opaque_layers) {} 2417 void RunMyTest() { 2418 typename Types::ContentLayerType* parent = this->CreateRoot( 2419 this->identity_matrix, gfx::PointF(), gfx::Size(300, 300)); 2420 typename Types::ContentLayerType* layer = 2421 this->CreateDrawingLayer(parent, 2422 this->identity_matrix, 2423 gfx::PointF(), 2424 gfx::Size(300, 300), 2425 true); 2426 typename Types::ContentLayerType* surface = 2427 this->CreateDrawingSurface(parent, 2428 this->identity_matrix, 2429 gfx::PointF(), 2430 gfx::Size(300, 300), 2431 true); 2432 typename Types::ContentLayerType* surface_child = 2433 this->CreateDrawingLayer(surface, 2434 this->identity_matrix, 2435 gfx::PointF(), 2436 gfx::Size(200, 300), 2437 true); 2438 typename Types::ContentLayerType* surface_child2 = 2439 this->CreateDrawingLayer(surface, 2440 this->identity_matrix, 2441 gfx::PointF(), 2442 gfx::Size(100, 300), 2443 true); 2444 typename Types::ContentLayerType* surface2 = this->CreateDrawingSurface( 2445 parent, this->identity_matrix, gfx::PointF(), gfx::Size(50, 300), true); 2446 2447 AddAnimatedTransformToController( 2448 layer->layer_animation_controller(), 10.0, 30, 0); 2449 AddAnimatedTransformToController( 2450 surface->layer_animation_controller(), 10.0, 30, 0); 2451 AddAnimatedTransformToController( 2452 surface_child->layer_animation_controller(), 10.0, 30, 0); 2453 this->CalcDrawEtc(parent); 2454 2455 EXPECT_TRUE(layer->draw_transform_is_animating()); 2456 EXPECT_TRUE(layer->screen_space_transform_is_animating()); 2457 EXPECT_TRUE( 2458 surface->render_surface()->target_surface_transforms_are_animating()); 2459 EXPECT_TRUE( 2460 surface->render_surface()->screen_space_transforms_are_animating()); 2461 // The surface owning layer doesn't animate against its own surface. 2462 EXPECT_FALSE(surface->draw_transform_is_animating()); 2463 EXPECT_TRUE(surface->screen_space_transform_is_animating()); 2464 EXPECT_TRUE(surface_child->draw_transform_is_animating()); 2465 EXPECT_TRUE(surface_child->screen_space_transform_is_animating()); 2466 2467 TestOcclusionTrackerWithClip<typename Types::LayerType, 2468 typename Types::RenderSurfaceType> occlusion( 2469 gfx::Rect(0, 0, 1000, 1000)); 2470 2471 this->VisitLayer(surface2, &occlusion); 2472 this->EnterContributingSurface(surface2, &occlusion); 2473 2474 EXPECT_EQ(gfx::Rect(0, 0, 50, 300).ToString(), 2475 occlusion.occlusion_from_inside_target().ToString()); 2476 2477 this->LeaveContributingSurface(surface2, &occlusion); 2478 this->EnterLayer(surface_child2, &occlusion); 2479 2480 // surface_child2 is moving in screen space but not relative to its target, 2481 // so occlusion should happen in its target space only. It also means that 2482 // things occluding from outside the target (e.g. surface2) cannot occlude 2483 // this layer. 2484 EXPECT_EQ(gfx::Rect().ToString(), 2485 occlusion.occlusion_from_outside_target().ToString()); 2486 2487 EXPECT_RECT_EQ(gfx::Rect(0, 0, 100, 300), 2488 occlusion.UnoccludedLayerContentRect( 2489 surface_child2, gfx::Rect(0, 0, 100, 300))); 2490 EXPECT_FALSE( 2491 occlusion.OccludedLayer(surface_child, gfx::Rect(0, 0, 50, 300))); 2492 2493 this->LeaveLayer(surface_child2, &occlusion); 2494 this->EnterLayer(surface_child, &occlusion); 2495 EXPECT_FALSE( 2496 occlusion.OccludedLayer(surface_child, gfx::Rect(0, 0, 100, 300))); 2497 EXPECT_EQ(gfx::Rect().ToString(), 2498 occlusion.occlusion_from_outside_target().ToString()); 2499 EXPECT_EQ(gfx::Rect(0, 0, 100, 300).ToString(), 2500 occlusion.occlusion_from_inside_target().ToString()); 2501 EXPECT_RECT_EQ(gfx::Rect(100, 0, 200, 300), 2502 occlusion.UnoccludedLayerContentRect( 2503 surface, gfx::Rect(0, 0, 300, 300))); 2504 2505 // The surface_child is occluded by the surface_child2, but is moving 2506 // relative its target, so it can't be occluded. 2507 EXPECT_RECT_EQ(gfx::Rect(0, 0, 200, 300), 2508 occlusion.UnoccludedLayerContentRect( 2509 surface_child, gfx::Rect(0, 0, 200, 300))); 2510 EXPECT_FALSE( 2511 occlusion.OccludedLayer(surface_child, gfx::Rect(0, 0, 50, 300))); 2512 2513 this->LeaveLayer(surface_child, &occlusion); 2514 this->EnterLayer(surface, &occlusion); 2515 // The surface_child is moving in screen space but not relative to its 2516 // target, so occlusion should happen from within the target only. 2517 EXPECT_EQ(gfx::Rect().ToString(), 2518 occlusion.occlusion_from_outside_target().ToString()); 2519 EXPECT_EQ(gfx::Rect(0, 0, 100, 300).ToString(), 2520 occlusion.occlusion_from_inside_target().ToString()); 2521 EXPECT_RECT_EQ(gfx::Rect(100, 0, 200, 300), 2522 occlusion.UnoccludedLayerContentRect( 2523 surface, gfx::Rect(0, 0, 300, 300))); 2524 2525 this->LeaveLayer(surface, &occlusion); 2526 // The surface's owning layer is moving in screen space but not relative to 2527 // its target, so occlusion should happen within the target only. 2528 EXPECT_EQ(gfx::Rect().ToString(), 2529 occlusion.occlusion_from_outside_target().ToString()); 2530 EXPECT_EQ(gfx::Rect(0, 0, 300, 300).ToString(), 2531 occlusion.occlusion_from_inside_target().ToString()); 2532 EXPECT_RECT_EQ(gfx::Rect(0, 0, 0, 0), 2533 occlusion.UnoccludedLayerContentRect( 2534 surface, gfx::Rect(0, 0, 300, 300))); 2535 2536 this->EnterContributingSurface(surface, &occlusion); 2537 // The contributing |surface| is animating so it can't be occluded. 2538 EXPECT_RECT_EQ(gfx::Rect(0, 0, 300, 300), 2539 occlusion.UnoccludedContributingSurfaceContentRect( 2540 surface, false, gfx::Rect(0, 0, 300, 300))); 2541 this->LeaveContributingSurface(surface, &occlusion); 2542 2543 this->EnterLayer(layer, &occlusion); 2544 // The |surface| is moving in the screen and in its target, so all occlusion 2545 // within the surface is lost when leaving it. 2546 EXPECT_RECT_EQ(gfx::Rect(50, 0, 250, 300), 2547 occlusion.UnoccludedLayerContentRect( 2548 parent, gfx::Rect(0, 0, 300, 300))); 2549 this->LeaveLayer(layer, &occlusion); 2550 2551 this->EnterLayer(parent, &occlusion); 2552 // The |layer| is animating in the screen and in its target, so no occlusion 2553 // is added. 2554 EXPECT_RECT_EQ(gfx::Rect(50, 0, 250, 300), 2555 occlusion.UnoccludedLayerContentRect( 2556 parent, gfx::Rect(0, 0, 300, 300))); 2557 } 2558 }; 2559 2560 MAIN_THREAD_TEST(OcclusionTrackerTestAnimationTranslateOnMainThread); 2561 2562 template <class Types> 2563 class OcclusionTrackerTestSurfaceOcclusionTranslatesToParent 2564 : public OcclusionTrackerTest<Types> { 2565 protected: 2566 explicit OcclusionTrackerTestSurfaceOcclusionTranslatesToParent( 2567 bool opaque_layers) 2568 : OcclusionTrackerTest<Types>(opaque_layers) {} 2569 void RunMyTest() { 2570 gfx::Transform surface_transform; 2571 surface_transform.Translate(300.0, 300.0); 2572 surface_transform.Scale(2.0, 2.0); 2573 surface_transform.Translate(-150.0, -150.0); 2574 2575 typename Types::ContentLayerType* parent = this->CreateRoot( 2576 this->identity_matrix, gfx::PointF(), gfx::Size(500, 500)); 2577 typename Types::ContentLayerType* surface = this->CreateDrawingSurface( 2578 parent, surface_transform, gfx::PointF(), gfx::Size(300, 300), false); 2579 typename Types::ContentLayerType* surface2 = 2580 this->CreateDrawingSurface(parent, 2581 this->identity_matrix, 2582 gfx::PointF(50.f, 50.f), 2583 gfx::Size(300, 300), 2584 false); 2585 surface->SetOpaqueContentsRect(gfx::Rect(0, 0, 200, 200)); 2586 surface2->SetOpaqueContentsRect(gfx::Rect(0, 0, 200, 200)); 2587 this->CalcDrawEtc(parent); 2588 2589 TestOcclusionTrackerWithClip<typename Types::LayerType, 2590 typename Types::RenderSurfaceType> occlusion( 2591 gfx::Rect(0, 0, 1000, 1000)); 2592 2593 this->VisitLayer(surface2, &occlusion); 2594 this->VisitContributingSurface(surface2, &occlusion); 2595 2596 EXPECT_EQ(gfx::Rect().ToString(), 2597 occlusion.occlusion_from_outside_target().ToString()); 2598 EXPECT_EQ(gfx::Rect(50, 50, 200, 200).ToString(), 2599 occlusion.occlusion_from_inside_target().ToString()); 2600 2601 // Clear any stored occlusion. 2602 occlusion.set_occlusion_from_outside_target(Region()); 2603 occlusion.set_occlusion_from_inside_target(Region()); 2604 2605 this->VisitLayer(surface, &occlusion); 2606 this->VisitContributingSurface(surface, &occlusion); 2607 2608 EXPECT_EQ(gfx::Rect().ToString(), 2609 occlusion.occlusion_from_outside_target().ToString()); 2610 EXPECT_EQ(gfx::Rect(0, 0, 400, 400).ToString(), 2611 occlusion.occlusion_from_inside_target().ToString()); 2612 } 2613 }; 2614 2615 MAIN_AND_IMPL_THREAD_TEST( 2616 OcclusionTrackerTestSurfaceOcclusionTranslatesToParent); 2617 2618 template <class Types> 2619 class OcclusionTrackerTestSurfaceOcclusionTranslatesWithClipping 2620 : public OcclusionTrackerTest<Types> { 2621 protected: 2622 explicit OcclusionTrackerTestSurfaceOcclusionTranslatesWithClipping( 2623 bool opaque_layers) 2624 : OcclusionTrackerTest<Types>(opaque_layers) {} 2625 void RunMyTest() { 2626 typename Types::ContentLayerType* parent = this->CreateRoot( 2627 this->identity_matrix, gfx::PointF(), gfx::Size(300, 300)); 2628 parent->SetMasksToBounds(true); 2629 typename Types::ContentLayerType* surface = 2630 this->CreateDrawingSurface(parent, 2631 this->identity_matrix, 2632 gfx::PointF(), 2633 gfx::Size(500, 300), 2634 false); 2635 surface->SetOpaqueContentsRect(gfx::Rect(0, 0, 400, 200)); 2636 this->CalcDrawEtc(parent); 2637 2638 TestOcclusionTrackerWithClip<typename Types::LayerType, 2639 typename Types::RenderSurfaceType> occlusion( 2640 gfx::Rect(0, 0, 1000, 1000)); 2641 2642 this->VisitLayer(surface, &occlusion); 2643 this->VisitContributingSurface(surface, &occlusion); 2644 2645 EXPECT_EQ(gfx::Rect().ToString(), 2646 occlusion.occlusion_from_outside_target().ToString()); 2647 EXPECT_EQ(gfx::Rect(0, 0, 300, 200).ToString(), 2648 occlusion.occlusion_from_inside_target().ToString()); 2649 } 2650 }; 2651 2652 MAIN_AND_IMPL_THREAD_TEST( 2653 OcclusionTrackerTestSurfaceOcclusionTranslatesWithClipping); 2654 2655 template <class Types> 2656 class OcclusionTrackerTestReplicaOccluded : public OcclusionTrackerTest<Types> { 2657 protected: 2658 explicit OcclusionTrackerTestReplicaOccluded(bool opaque_layers) 2659 : OcclusionTrackerTest<Types>(opaque_layers) {} 2660 void RunMyTest() { 2661 typename Types::ContentLayerType* parent = this->CreateRoot( 2662 this->identity_matrix, gfx::PointF(), gfx::Size(100, 200)); 2663 typename Types::LayerType* surface = 2664 this->CreateDrawingSurface(parent, 2665 this->identity_matrix, 2666 gfx::PointF(), 2667 gfx::Size(100, 100), 2668 true); 2669 this->CreateReplicaLayer(surface, 2670 this->identity_matrix, 2671 gfx::PointF(0.f, 100.f), 2672 gfx::Size(100, 100)); 2673 typename Types::LayerType* topmost = 2674 this->CreateDrawingLayer(parent, 2675 this->identity_matrix, 2676 gfx::PointF(0.f, 100.f), 2677 gfx::Size(100, 100), 2678 true); 2679 this->CalcDrawEtc(parent); 2680 2681 TestOcclusionTrackerWithClip<typename Types::LayerType, 2682 typename Types::RenderSurfaceType> occlusion( 2683 gfx::Rect(0, 0, 1000, 1000)); 2684 2685 // |topmost| occludes the replica, but not the surface itself. 2686 this->VisitLayer(topmost, &occlusion); 2687 2688 EXPECT_EQ(gfx::Rect().ToString(), 2689 occlusion.occlusion_from_outside_target().ToString()); 2690 EXPECT_EQ(gfx::Rect(0, 100, 100, 100).ToString(), 2691 occlusion.occlusion_from_inside_target().ToString()); 2692 2693 this->VisitLayer(surface, &occlusion); 2694 2695 // Render target with replica ignores occlusion from outside. 2696 EXPECT_EQ(gfx::Rect().ToString(), 2697 occlusion.occlusion_from_outside_target().ToString()); 2698 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), 2699 occlusion.occlusion_from_inside_target().ToString()); 2700 2701 this->EnterContributingSurface(surface, &occlusion); 2702 2703 // Surface is not occluded so it shouldn't think it is. 2704 EXPECT_RECT_EQ(gfx::Rect(0, 0, 100, 100), 2705 occlusion.UnoccludedContributingSurfaceContentRect( 2706 surface, false, gfx::Rect(0, 0, 100, 100))); 2707 } 2708 }; 2709 2710 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestReplicaOccluded); 2711 2712 template <class Types> 2713 class OcclusionTrackerTestSurfaceWithReplicaUnoccluded 2714 : public OcclusionTrackerTest<Types> { 2715 protected: 2716 explicit OcclusionTrackerTestSurfaceWithReplicaUnoccluded(bool opaque_layers) 2717 : OcclusionTrackerTest<Types>(opaque_layers) {} 2718 void RunMyTest() { 2719 typename Types::ContentLayerType* parent = this->CreateRoot( 2720 this->identity_matrix, gfx::PointF(), gfx::Size(100, 200)); 2721 typename Types::LayerType* surface = 2722 this->CreateDrawingSurface(parent, 2723 this->identity_matrix, 2724 gfx::PointF(), 2725 gfx::Size(100, 100), 2726 true); 2727 this->CreateReplicaLayer(surface, 2728 this->identity_matrix, 2729 gfx::PointF(0.f, 100.f), 2730 gfx::Size(100, 100)); 2731 typename Types::LayerType* topmost = 2732 this->CreateDrawingLayer(parent, 2733 this->identity_matrix, 2734 gfx::PointF(), 2735 gfx::Size(100, 110), 2736 true); 2737 this->CalcDrawEtc(parent); 2738 2739 TestOcclusionTrackerWithClip<typename Types::LayerType, 2740 typename Types::RenderSurfaceType> occlusion( 2741 gfx::Rect(0, 0, 1000, 1000)); 2742 2743 // |topmost| occludes the surface, but not the entire surface's replica. 2744 this->VisitLayer(topmost, &occlusion); 2745 2746 EXPECT_EQ(gfx::Rect().ToString(), 2747 occlusion.occlusion_from_outside_target().ToString()); 2748 EXPECT_EQ(gfx::Rect(0, 0, 100, 110).ToString(), 2749 occlusion.occlusion_from_inside_target().ToString()); 2750 2751 this->VisitLayer(surface, &occlusion); 2752 2753 // Render target with replica ignores occlusion from outside. 2754 EXPECT_EQ(gfx::Rect().ToString(), 2755 occlusion.occlusion_from_outside_target().ToString()); 2756 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), 2757 occlusion.occlusion_from_inside_target().ToString()); 2758 2759 this->EnterContributingSurface(surface, &occlusion); 2760 2761 // Surface is occluded, but only the top 10px of the replica. 2762 EXPECT_RECT_EQ(gfx::Rect(0, 0, 0, 0), 2763 occlusion.UnoccludedContributingSurfaceContentRect( 2764 surface, false, gfx::Rect(0, 0, 100, 100))); 2765 EXPECT_RECT_EQ(gfx::Rect(0, 10, 100, 90), 2766 occlusion.UnoccludedContributingSurfaceContentRect( 2767 surface, true, gfx::Rect(0, 0, 100, 100))); 2768 } 2769 }; 2770 2771 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestSurfaceWithReplicaUnoccluded); 2772 2773 template <class Types> 2774 class OcclusionTrackerTestSurfaceAndReplicaOccludedDifferently 2775 : public OcclusionTrackerTest<Types> { 2776 protected: 2777 explicit OcclusionTrackerTestSurfaceAndReplicaOccludedDifferently( 2778 bool opaque_layers) 2779 : OcclusionTrackerTest<Types>(opaque_layers) {} 2780 void RunMyTest() { 2781 typename Types::ContentLayerType* parent = this->CreateRoot( 2782 this->identity_matrix, gfx::PointF(), gfx::Size(100, 200)); 2783 typename Types::LayerType* surface = 2784 this->CreateDrawingSurface(parent, 2785 this->identity_matrix, 2786 gfx::PointF(), 2787 gfx::Size(100, 100), 2788 true); 2789 this->CreateReplicaLayer(surface, 2790 this->identity_matrix, 2791 gfx::PointF(0.f, 100.f), 2792 gfx::Size(100, 100)); 2793 typename Types::LayerType* over_surface = this->CreateDrawingLayer( 2794 parent, this->identity_matrix, gfx::PointF(), gfx::Size(40, 100), true); 2795 typename Types::LayerType* over_replica = 2796 this->CreateDrawingLayer(parent, 2797 this->identity_matrix, 2798 gfx::PointF(0.f, 100.f), 2799 gfx::Size(50, 100), 2800 true); 2801 this->CalcDrawEtc(parent); 2802 2803 TestOcclusionTrackerWithClip<typename Types::LayerType, 2804 typename Types::RenderSurfaceType> occlusion( 2805 gfx::Rect(0, 0, 1000, 1000)); 2806 2807 // These occlude the surface and replica differently, so we can test each 2808 // one. 2809 this->VisitLayer(over_replica, &occlusion); 2810 this->VisitLayer(over_surface, &occlusion); 2811 2812 EXPECT_EQ(gfx::Rect().ToString(), 2813 occlusion.occlusion_from_outside_target().ToString()); 2814 EXPECT_EQ(UnionRegions(gfx::Rect(0, 0, 40, 100), gfx::Rect(0, 100, 50, 100)) 2815 .ToString(), 2816 occlusion.occlusion_from_inside_target().ToString()); 2817 2818 this->VisitLayer(surface, &occlusion); 2819 2820 // Render target with replica ignores occlusion from outside. 2821 EXPECT_EQ(gfx::Rect().ToString(), 2822 occlusion.occlusion_from_outside_target().ToString()); 2823 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), 2824 occlusion.occlusion_from_inside_target().ToString()); 2825 2826 this->EnterContributingSurface(surface, &occlusion); 2827 2828 // Surface and replica are occluded different amounts. 2829 EXPECT_RECT_EQ(gfx::Rect(40, 0, 60, 100), 2830 occlusion.UnoccludedContributingSurfaceContentRect( 2831 surface, false, gfx::Rect(0, 0, 100, 100))); 2832 EXPECT_RECT_EQ(gfx::Rect(50, 0, 50, 100), 2833 occlusion.UnoccludedContributingSurfaceContentRect( 2834 surface, true, gfx::Rect(0, 0, 100, 100))); 2835 } 2836 }; 2837 2838 ALL_OCCLUSIONTRACKER_TEST( 2839 OcclusionTrackerTestSurfaceAndReplicaOccludedDifferently); 2840 2841 template <class Types> 2842 class OcclusionTrackerTestSurfaceChildOfSurface 2843 : public OcclusionTrackerTest<Types> { 2844 protected: 2845 explicit OcclusionTrackerTestSurfaceChildOfSurface(bool opaque_layers) 2846 : OcclusionTrackerTest<Types>(opaque_layers) {} 2847 void RunMyTest() { 2848 // This test verifies that the surface cliprect does not end up empty and 2849 // clip away the entire unoccluded rect. 2850 2851 typename Types::ContentLayerType* parent = this->CreateRoot( 2852 this->identity_matrix, gfx::PointF(), gfx::Size(100, 200)); 2853 typename Types::LayerType* surface = 2854 this->CreateDrawingSurface(parent, 2855 this->identity_matrix, 2856 gfx::PointF(), 2857 gfx::Size(100, 100), 2858 true); 2859 typename Types::LayerType* surface_child = 2860 this->CreateDrawingSurface(surface, 2861 this->identity_matrix, 2862 gfx::PointF(0.f, 10.f), 2863 gfx::Size(100, 50), 2864 true); 2865 typename Types::LayerType* topmost = this->CreateDrawingLayer( 2866 parent, this->identity_matrix, gfx::PointF(), gfx::Size(100, 50), true); 2867 this->CalcDrawEtc(parent); 2868 2869 TestOcclusionTrackerWithClip<typename Types::LayerType, 2870 typename Types::RenderSurfaceType> occlusion( 2871 gfx::Rect(-100, -100, 1000, 1000)); 2872 2873 // |topmost| occludes everything partially so we know occlusion is happening 2874 // at all. 2875 this->VisitLayer(topmost, &occlusion); 2876 2877 EXPECT_EQ(gfx::Rect().ToString(), 2878 occlusion.occlusion_from_outside_target().ToString()); 2879 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(), 2880 occlusion.occlusion_from_inside_target().ToString()); 2881 2882 this->VisitLayer(surface_child, &occlusion); 2883 2884 // surface_child increases the occlusion in the screen by a narrow sliver. 2885 EXPECT_EQ(gfx::Rect(0, -10, 100, 50).ToString(), 2886 occlusion.occlusion_from_outside_target().ToString()); 2887 // In its own surface, surface_child is at 0,0 as is its occlusion. 2888 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(), 2889 occlusion.occlusion_from_inside_target().ToString()); 2890 2891 // The root layer always has a clip rect. So the parent of |surface| has a 2892 // clip rect. However, the owning layer for |surface| does not mask to 2893 // bounds, so it doesn't have a clip rect of its own. Thus the parent of 2894 // |surface_child| exercises different code paths as its parent does not 2895 // have a clip rect. 2896 2897 this->EnterContributingSurface(surface_child, &occlusion); 2898 // The surface_child's parent does not have a clip rect as it owns a render 2899 // surface. Make sure the unoccluded rect does not get clipped away 2900 // inappropriately. 2901 EXPECT_RECT_EQ(gfx::Rect(0, 40, 100, 10), 2902 occlusion.UnoccludedContributingSurfaceContentRect( 2903 surface_child, false, gfx::Rect(0, 0, 100, 50))); 2904 this->LeaveContributingSurface(surface_child, &occlusion); 2905 2906 // When the surface_child's occlusion is transformed up to its parent, make 2907 // sure it is not clipped away inappropriately also. 2908 this->EnterLayer(surface, &occlusion); 2909 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(), 2910 occlusion.occlusion_from_outside_target().ToString()); 2911 EXPECT_EQ(gfx::Rect(0, 10, 100, 50).ToString(), 2912 occlusion.occlusion_from_inside_target().ToString()); 2913 this->LeaveLayer(surface, &occlusion); 2914 2915 this->EnterContributingSurface(surface, &occlusion); 2916 // The surface's parent does have a clip rect as it is the root layer. 2917 EXPECT_RECT_EQ(gfx::Rect(0, 50, 100, 50), 2918 occlusion.UnoccludedContributingSurfaceContentRect( 2919 surface, false, gfx::Rect(0, 0, 100, 100))); 2920 } 2921 }; 2922 2923 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestSurfaceChildOfSurface); 2924 2925 template <class Types> 2926 class OcclusionTrackerTestTopmostSurfaceIsClippedToViewport 2927 : public OcclusionTrackerTest<Types> { 2928 protected: 2929 explicit OcclusionTrackerTestTopmostSurfaceIsClippedToViewport( 2930 bool opaque_layers) 2931 : OcclusionTrackerTest<Types>(opaque_layers) {} 2932 void RunMyTest() { 2933 // This test verifies that the top-most surface is considered occluded 2934 // outside of its target's clip rect and outside the viewport rect. 2935 2936 typename Types::ContentLayerType* parent = this->CreateRoot( 2937 this->identity_matrix, gfx::PointF(), gfx::Size(100, 200)); 2938 typename Types::LayerType* surface = 2939 this->CreateDrawingSurface(parent, 2940 this->identity_matrix, 2941 gfx::PointF(), 2942 gfx::Size(100, 300), 2943 true); 2944 this->CalcDrawEtc(parent); 2945 { 2946 // Make a viewport rect that is larger than the root layer. 2947 TestOcclusionTrackerWithClip<typename Types::LayerType, 2948 typename Types::RenderSurfaceType> occlusion( 2949 gfx::Rect(0, 0, 1000, 1000)); 2950 2951 this->VisitLayer(surface, &occlusion); 2952 2953 // The root layer always has a clip rect. So the parent of |surface| has a 2954 // clip rect giving the surface itself a clip rect. 2955 this->EnterContributingSurface(surface, &occlusion); 2956 // Make sure the parent's clip rect clips the unoccluded region of the 2957 // child surface. 2958 EXPECT_RECT_EQ(gfx::Rect(0, 0, 100, 200), 2959 occlusion.UnoccludedContributingSurfaceContentRect( 2960 surface, false, gfx::Rect(0, 0, 100, 300))); 2961 } 2962 this->ResetLayerIterator(); 2963 { 2964 // Make a viewport rect that is smaller than the root layer. 2965 TestOcclusionTrackerWithClip<typename Types::LayerType, 2966 typename Types::RenderSurfaceType> occlusion( 2967 gfx::Rect(0, 0, 100, 100)); 2968 2969 this->VisitLayer(surface, &occlusion); 2970 2971 // The root layer always has a clip rect. So the parent of |surface| has a 2972 // clip rect giving the surface itself a clip rect. 2973 this->EnterContributingSurface(surface, &occlusion); 2974 // Make sure the viewport rect clips the unoccluded region of the child 2975 // surface. 2976 EXPECT_RECT_EQ(gfx::Rect(0, 0, 100, 100), 2977 occlusion.UnoccludedContributingSurfaceContentRect( 2978 surface, false, gfx::Rect(0, 0, 100, 300))); 2979 } 2980 } 2981 }; 2982 2983 ALL_OCCLUSIONTRACKER_TEST( 2984 OcclusionTrackerTestTopmostSurfaceIsClippedToViewport); 2985 2986 template <class Types> 2987 class OcclusionTrackerTestSurfaceChildOfClippingSurface 2988 : public OcclusionTrackerTest<Types> { 2989 protected: 2990 explicit OcclusionTrackerTestSurfaceChildOfClippingSurface(bool opaque_layers) 2991 : OcclusionTrackerTest<Types>(opaque_layers) {} 2992 void RunMyTest() { 2993 // This test verifies that the surface cliprect does not end up empty and 2994 // clip away the entire unoccluded rect. 2995 2996 typename Types::ContentLayerType* parent = this->CreateRoot( 2997 this->identity_matrix, gfx::PointF(), gfx::Size(80, 200)); 2998 parent->SetMasksToBounds(true); 2999 typename Types::LayerType* surface = 3000 this->CreateDrawingSurface(parent, 3001 this->identity_matrix, 3002 gfx::PointF(), 3003 gfx::Size(100, 100), 3004 true); 3005 typename Types::LayerType* surface_child = 3006 this->CreateDrawingSurface(surface, 3007 this->identity_matrix, 3008 gfx::PointF(), 3009 gfx::Size(100, 100), 3010 false); 3011 typename Types::LayerType* topmost = this->CreateDrawingLayer( 3012 parent, this->identity_matrix, gfx::PointF(), gfx::Size(100, 50), true); 3013 this->CalcDrawEtc(parent); 3014 3015 TestOcclusionTrackerWithClip<typename Types::LayerType, 3016 typename Types::RenderSurfaceType> occlusion( 3017 gfx::Rect(0, 0, 1000, 1000)); 3018 3019 // |topmost| occludes everything partially so we know occlusion is happening 3020 // at all. 3021 this->VisitLayer(topmost, &occlusion); 3022 3023 EXPECT_EQ(gfx::Rect().ToString(), 3024 occlusion.occlusion_from_outside_target().ToString()); 3025 EXPECT_EQ(gfx::Rect(0, 0, 80, 50).ToString(), 3026 occlusion.occlusion_from_inside_target().ToString()); 3027 3028 // surface_child is not opaque and does not occlude, so we have a non-empty 3029 // unoccluded area on surface. 3030 this->VisitLayer(surface_child, &occlusion); 3031 3032 EXPECT_EQ(gfx::Rect(0, 0, 80, 50).ToString(), 3033 occlusion.occlusion_from_outside_target().ToString()); 3034 EXPECT_EQ(gfx::Rect(0, 0, 0, 0).ToString(), 3035 occlusion.occlusion_from_inside_target().ToString()); 3036 3037 // The root layer always has a clip rect. So the parent of |surface| has a 3038 // clip rect. However, the owning layer for |surface| does not mask to 3039 // bounds, so it doesn't have a clip rect of its own. Thus the parent of 3040 // |surface_child| exercises different code paths as its parent does not 3041 // have a clip rect. 3042 3043 this->EnterContributingSurface(surface_child, &occlusion); 3044 // The surface_child's parent does not have a clip rect as it owns a render 3045 // surface. 3046 EXPECT_EQ( 3047 gfx::Rect(0, 50, 80, 50).ToString(), 3048 occlusion.UnoccludedContributingSurfaceContentRect( 3049 surface_child, false, gfx::Rect(0, 0, 100, 100)).ToString()); 3050 this->LeaveContributingSurface(surface_child, &occlusion); 3051 3052 this->VisitLayer(surface, &occlusion); 3053 this->EnterContributingSurface(surface, &occlusion); 3054 // The surface's parent does have a clip rect as it is the root layer. 3055 EXPECT_EQ(gfx::Rect(0, 50, 80, 50).ToString(), 3056 occlusion.UnoccludedContributingSurfaceContentRect( 3057 surface, false, gfx::Rect(0, 0, 100, 100)).ToString()); 3058 } 3059 }; 3060 3061 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestSurfaceChildOfClippingSurface); 3062 3063 template <class Types> 3064 class OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilter 3065 : public OcclusionTrackerTest<Types> { 3066 protected: 3067 explicit OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilter( 3068 bool opaque_layers) 3069 : OcclusionTrackerTest<Types>(opaque_layers) {} 3070 void RunMyTest() { 3071 gfx::Transform scale_by_half; 3072 scale_by_half.Scale(0.5, 0.5); 3073 3074 // Make a 50x50 filtered surface that is completely surrounded by opaque 3075 // layers which are above it in the z-order. The surface is scaled to test 3076 // that the pixel moving is done in the target space, where the background 3077 // filter is applied. 3078 typename Types::ContentLayerType* parent = this->CreateRoot( 3079 this->identity_matrix, gfx::PointF(), gfx::Size(200, 150)); 3080 typename Types::LayerType* filtered_surface = 3081 this->CreateDrawingLayer(parent, 3082 scale_by_half, 3083 gfx::PointF(50.f, 50.f), 3084 gfx::Size(100, 100), 3085 false); 3086 typename Types::LayerType* occluding_layer1 = this->CreateDrawingLayer( 3087 parent, this->identity_matrix, gfx::PointF(), gfx::Size(200, 50), true); 3088 typename Types::LayerType* occluding_layer2 = 3089 this->CreateDrawingLayer(parent, 3090 this->identity_matrix, 3091 gfx::PointF(0.f, 100.f), 3092 gfx::Size(200, 50), 3093 true); 3094 typename Types::LayerType* occluding_layer3 = 3095 this->CreateDrawingLayer(parent, 3096 this->identity_matrix, 3097 gfx::PointF(0.f, 50.f), 3098 gfx::Size(50, 50), 3099 true); 3100 typename Types::LayerType* occluding_layer4 = 3101 this->CreateDrawingLayer(parent, 3102 this->identity_matrix, 3103 gfx::PointF(100.f, 50.f), 3104 gfx::Size(100, 50), 3105 true); 3106 3107 // Filters make the layer own a surface. 3108 FilterOperations filters; 3109 filters.Append(FilterOperation::CreateBlurFilter(10.f)); 3110 filtered_surface->SetBackgroundFilters(filters); 3111 3112 // Save the distance of influence for the blur effect. 3113 int outset_top, outset_right, outset_bottom, outset_left; 3114 filters.GetOutsets( 3115 &outset_top, &outset_right, &outset_bottom, &outset_left); 3116 3117 this->CalcDrawEtc(parent); 3118 3119 TestOcclusionTrackerWithClip<typename Types::LayerType, 3120 typename Types::RenderSurfaceType> occlusion( 3121 gfx::Rect(0, 0, 1000, 1000)); 3122 3123 // These layers occlude pixels directly beside the filtered_surface. Because 3124 // filtered surface blends pixels in a radius, it will need to see some of 3125 // the pixels (up to radius far) underneath the occluding layers. 3126 this->VisitLayer(occluding_layer4, &occlusion); 3127 this->VisitLayer(occluding_layer3, &occlusion); 3128 this->VisitLayer(occluding_layer2, &occlusion); 3129 this->VisitLayer(occluding_layer1, &occlusion); 3130 3131 Region expected_occlusion; 3132 expected_occlusion.Union(gfx::Rect(0, 0, 200, 50)); 3133 expected_occlusion.Union(gfx::Rect(0, 50, 50, 50)); 3134 expected_occlusion.Union(gfx::Rect(100, 50, 100, 50)); 3135 expected_occlusion.Union(gfx::Rect(0, 100, 200, 50)); 3136 3137 EXPECT_EQ(expected_occlusion.ToString(), 3138 occlusion.occlusion_from_inside_target().ToString()); 3139 EXPECT_EQ(gfx::Rect().ToString(), 3140 occlusion.occlusion_from_outside_target().ToString()); 3141 3142 this->VisitLayer(filtered_surface, &occlusion); 3143 3144 // The filtered layer does not occlude. 3145 Region expected_occlusion_outside_surface; 3146 expected_occlusion_outside_surface.Union(gfx::Rect(-50, -50, 200, 50)); 3147 expected_occlusion_outside_surface.Union(gfx::Rect(-50, 0, 50, 50)); 3148 expected_occlusion_outside_surface.Union(gfx::Rect(50, 0, 100, 50)); 3149 expected_occlusion_outside_surface.Union(gfx::Rect(-50, 50, 200, 50)); 3150 3151 EXPECT_EQ(expected_occlusion_outside_surface.ToString(), 3152 occlusion.occlusion_from_outside_target().ToString()); 3153 EXPECT_EQ(gfx::Rect().ToString(), 3154 occlusion.occlusion_from_inside_target().ToString()); 3155 3156 // The surface has a background blur, so it needs pixels that are currently 3157 // considered occluded in order to be drawn. So the pixels it needs should 3158 // be removed some the occluded area so that when we get to the parent they 3159 // are drawn. 3160 this->VisitContributingSurface(filtered_surface, &occlusion); 3161 3162 this->EnterLayer(parent, &occlusion); 3163 3164 Region expected_blurred_occlusion; 3165 expected_blurred_occlusion.Union(gfx::Rect(0, 0, 200, 50 - outset_top)); 3166 expected_blurred_occlusion.Union(gfx::Rect( 3167 0, 50 - outset_top, 50 - outset_left, 50 + outset_top + outset_bottom)); 3168 expected_blurred_occlusion.Union( 3169 gfx::Rect(100 + outset_right, 3170 50 - outset_top, 3171 100 - outset_right, 3172 50 + outset_top + outset_bottom)); 3173 expected_blurred_occlusion.Union( 3174 gfx::Rect(0, 100 + outset_bottom, 200, 50 - outset_bottom)); 3175 3176 EXPECT_EQ(expected_blurred_occlusion.ToString(), 3177 occlusion.occlusion_from_inside_target().ToString()); 3178 EXPECT_EQ(gfx::Rect().ToString(), 3179 occlusion.occlusion_from_outside_target().ToString()); 3180 3181 gfx::Rect outset_rect; 3182 gfx::Rect test_rect; 3183 3184 // Nothing in the blur outsets for the filtered_surface is occluded. 3185 outset_rect = gfx::Rect(50 - outset_left, 3186 50 - outset_top, 3187 50 + outset_left + outset_right, 3188 50 + outset_top + outset_bottom); 3189 test_rect = outset_rect; 3190 EXPECT_EQ( 3191 outset_rect.ToString(), 3192 occlusion.UnoccludedLayerContentRect(parent, test_rect).ToString()); 3193 3194 // Stuff outside the blur outsets is still occluded though. 3195 test_rect = outset_rect; 3196 test_rect.Inset(0, 0, -1, 0); 3197 EXPECT_EQ( 3198 outset_rect.ToString(), 3199 occlusion.UnoccludedLayerContentRect(parent, test_rect).ToString()); 3200 test_rect = outset_rect; 3201 test_rect.Inset(0, 0, 0, -1); 3202 EXPECT_EQ( 3203 outset_rect.ToString(), 3204 occlusion.UnoccludedLayerContentRect(parent, test_rect).ToString()); 3205 test_rect = outset_rect; 3206 test_rect.Inset(-1, 0, 0, 0); 3207 EXPECT_EQ( 3208 outset_rect.ToString(), 3209 occlusion.UnoccludedLayerContentRect(parent, test_rect).ToString()); 3210 test_rect = outset_rect; 3211 test_rect.Inset(0, -1, 0, 0); 3212 EXPECT_EQ( 3213 outset_rect.ToString(), 3214 occlusion.UnoccludedLayerContentRect(parent, test_rect).ToString()); 3215 } 3216 }; 3217 3218 ALL_OCCLUSIONTRACKER_TEST( 3219 OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilter); 3220 3221 template <class Types> 3222 class OcclusionTrackerTestTwoBackgroundFiltersReduceOcclusionTwice 3223 : public OcclusionTrackerTest<Types> { 3224 protected: 3225 explicit OcclusionTrackerTestTwoBackgroundFiltersReduceOcclusionTwice( 3226 bool opaque_layers) 3227 : OcclusionTrackerTest<Types>(opaque_layers) {} 3228 void RunMyTest() { 3229 gfx::Transform scale_by_half; 3230 scale_by_half.Scale(0.5, 0.5); 3231 3232 // Makes two surfaces that completely cover |parent|. The occlusion both 3233 // above and below the filters will be reduced by each of them. 3234 typename Types::ContentLayerType* root = this->CreateRoot( 3235 this->identity_matrix, gfx::PointF(), gfx::Size(75, 75)); 3236 typename Types::LayerType* parent = this->CreateSurface( 3237 root, scale_by_half, gfx::PointF(), gfx::Size(150, 150)); 3238 parent->SetMasksToBounds(true); 3239 typename Types::LayerType* filtered_surface1 = this->CreateDrawingLayer( 3240 parent, scale_by_half, gfx::PointF(), gfx::Size(300, 300), false); 3241 typename Types::LayerType* filtered_surface2 = this->CreateDrawingLayer( 3242 parent, scale_by_half, gfx::PointF(), gfx::Size(300, 300), false); 3243 typename Types::LayerType* occluding_layer_above = 3244 this->CreateDrawingLayer(parent, 3245 this->identity_matrix, 3246 gfx::PointF(100.f, 100.f), 3247 gfx::Size(50, 50), 3248 true); 3249 3250 // Filters make the layers own surfaces. 3251 FilterOperations filters; 3252 filters.Append(FilterOperation::CreateBlurFilter(1.f)); 3253 filtered_surface1->SetBackgroundFilters(filters); 3254 filtered_surface2->SetBackgroundFilters(filters); 3255 3256 // Save the distance of influence for the blur effect. 3257 int outset_top, outset_right, outset_bottom, outset_left; 3258 filters.GetOutsets( 3259 &outset_top, &outset_right, &outset_bottom, &outset_left); 3260 3261 this->CalcDrawEtc(root); 3262 3263 TestOcclusionTrackerWithClip<typename Types::LayerType, 3264 typename Types::RenderSurfaceType> occlusion( 3265 gfx::Rect(0, 0, 1000, 1000)); 3266 3267 this->VisitLayer(occluding_layer_above, &occlusion); 3268 EXPECT_EQ(gfx::Rect().ToString(), 3269 occlusion.occlusion_from_outside_target().ToString()); 3270 EXPECT_EQ(gfx::Rect(100 / 2, 100 / 2, 50 / 2, 50 / 2).ToString(), 3271 occlusion.occlusion_from_inside_target().ToString()); 3272 3273 this->VisitLayer(filtered_surface2, &occlusion); 3274 this->VisitContributingSurface(filtered_surface2, &occlusion); 3275 this->VisitLayer(filtered_surface1, &occlusion); 3276 this->VisitContributingSurface(filtered_surface1, &occlusion); 3277 3278 // Test expectations in the target. 3279 gfx::Rect expected_occlusion = 3280 gfx::Rect(100 / 2 + outset_right * 2, 3281 100 / 2 + outset_bottom * 2, 3282 50 / 2 - (outset_left + outset_right) * 2, 3283 50 / 2 - (outset_top + outset_bottom) * 2); 3284 EXPECT_EQ(expected_occlusion.ToString(), 3285 occlusion.occlusion_from_inside_target().ToString()); 3286 3287 // Test expectations in the screen are the same as in the target, as the 3288 // render surface is 1:1 with the screen. 3289 EXPECT_EQ(expected_occlusion.ToString(), 3290 occlusion.occlusion_from_outside_target().ToString()); 3291 } 3292 }; 3293 3294 ALL_OCCLUSIONTRACKER_TEST( 3295 OcclusionTrackerTestTwoBackgroundFiltersReduceOcclusionTwice); 3296 3297 template <class Types> 3298 class OcclusionTrackerTestDontReduceOcclusionBelowBackgroundFilter 3299 : public OcclusionTrackerTest<Types> { 3300 protected: 3301 explicit OcclusionTrackerTestDontReduceOcclusionBelowBackgroundFilter( 3302 bool opaque_layers) 3303 : OcclusionTrackerTest<Types>(opaque_layers) {} 3304 void RunMyTest() { 3305 gfx::Transform scale_by_half; 3306 scale_by_half.Scale(0.5, 0.5); 3307 3308 // Make a surface and its replica, each 50x50, with a smaller 30x30 layer 3309 // centered below each. The surface is scaled to test that the pixel moving 3310 // is done in the target space, where the background filter is applied, but 3311 // the surface appears at 50, 50 and the replica at 200, 50. 3312 typename Types::ContentLayerType* parent = this->CreateRoot( 3313 this->identity_matrix, gfx::PointF(), gfx::Size(300, 150)); 3314 typename Types::LayerType* behind_surface_layer = 3315 this->CreateDrawingLayer(parent, 3316 this->identity_matrix, 3317 gfx::PointF(60.f, 60.f), 3318 gfx::Size(30, 30), 3319 true); 3320 typename Types::LayerType* behind_replica_layer = 3321 this->CreateDrawingLayer(parent, 3322 this->identity_matrix, 3323 gfx::PointF(210.f, 60.f), 3324 gfx::Size(30, 30), 3325 true); 3326 typename Types::LayerType* filtered_surface = 3327 this->CreateDrawingLayer(parent, 3328 scale_by_half, 3329 gfx::PointF(50.f, 50.f), 3330 gfx::Size(100, 100), 3331 false); 3332 this->CreateReplicaLayer(filtered_surface, 3333 this->identity_matrix, 3334 gfx::PointF(300.f, 0.f), 3335 gfx::Size()); 3336 3337 // Filters make the layer own a surface. 3338 FilterOperations filters; 3339 filters.Append(FilterOperation::CreateBlurFilter(3.f)); 3340 filtered_surface->SetBackgroundFilters(filters); 3341 3342 this->CalcDrawEtc(parent); 3343 3344 TestOcclusionTrackerWithClip<typename Types::LayerType, 3345 typename Types::RenderSurfaceType> occlusion( 3346 gfx::Rect(0, 0, 1000, 1000)); 3347 3348 // The surface has a background blur, so it blurs non-opaque pixels below 3349 // it. 3350 this->VisitLayer(filtered_surface, &occlusion); 3351 this->VisitContributingSurface(filtered_surface, &occlusion); 3352 3353 this->VisitLayer(behind_replica_layer, &occlusion); 3354 this->VisitLayer(behind_surface_layer, &occlusion); 3355 3356 // The layers behind the surface are not blurred, and their occlusion does 3357 // not change, until we leave the surface. So it should not be modified by 3358 // the filter here. 3359 gfx::Rect occlusion_behind_surface = gfx::Rect(60, 60, 30, 30); 3360 gfx::Rect occlusion_behind_replica = gfx::Rect(210, 60, 30, 30); 3361 3362 Region expected_opaque_bounds = 3363 UnionRegions(occlusion_behind_surface, occlusion_behind_replica); 3364 EXPECT_EQ(expected_opaque_bounds.ToString(), 3365 occlusion.occlusion_from_inside_target().ToString()); 3366 3367 EXPECT_EQ(gfx::Rect().ToString(), 3368 occlusion.occlusion_from_outside_target().ToString()); 3369 } 3370 }; 3371 3372 ALL_OCCLUSIONTRACKER_TEST( 3373 OcclusionTrackerTestDontReduceOcclusionBelowBackgroundFilter); 3374 3375 template <class Types> 3376 class OcclusionTrackerTestDontReduceOcclusionIfBackgroundFilterIsOccluded 3377 : public OcclusionTrackerTest<Types> { 3378 protected: 3379 explicit OcclusionTrackerTestDontReduceOcclusionIfBackgroundFilterIsOccluded( 3380 bool opaque_layers) 3381 : OcclusionTrackerTest<Types>(opaque_layers) {} 3382 void RunMyTest() { 3383 gfx::Transform scale_by_half; 3384 scale_by_half.Scale(0.5, 0.5); 3385 3386 // Make a 50x50 filtered surface that is completely occluded by an opaque 3387 // layer which is above it in the z-order. The surface is 3388 // scaled to test that the pixel moving is done in the target space, where 3389 // the background filter is applied, but the surface appears at 50, 50. 3390 typename Types::ContentLayerType* parent = this->CreateRoot( 3391 this->identity_matrix, gfx::PointF(), gfx::Size(200, 150)); 3392 typename Types::LayerType* filtered_surface = 3393 this->CreateDrawingLayer(parent, 3394 scale_by_half, 3395 gfx::PointF(50.f, 50.f), 3396 gfx::Size(100, 100), 3397 false); 3398 typename Types::LayerType* occluding_layer = 3399 this->CreateDrawingLayer(parent, 3400 this->identity_matrix, 3401 gfx::PointF(50.f, 50.f), 3402 gfx::Size(50, 50), 3403 true); 3404 3405 // Filters make the layer own a surface. 3406 FilterOperations filters; 3407 filters.Append(FilterOperation::CreateBlurFilter(3.f)); 3408 filtered_surface->SetBackgroundFilters(filters); 3409 3410 this->CalcDrawEtc(parent); 3411 3412 TestOcclusionTrackerWithClip<typename Types::LayerType, 3413 typename Types::RenderSurfaceType> occlusion( 3414 gfx::Rect(0, 0, 1000, 1000)); 3415 3416 this->VisitLayer(occluding_layer, &occlusion); 3417 3418 this->VisitLayer(filtered_surface, &occlusion); 3419 { 3420 // The layers above the filtered surface occlude from outside. 3421 gfx::Rect occlusion_above_surface = gfx::Rect(0, 0, 50, 50); 3422 3423 EXPECT_EQ(gfx::Rect().ToString(), 3424 occlusion.occlusion_from_inside_target().ToString()); 3425 EXPECT_EQ(occlusion_above_surface.ToString(), 3426 occlusion.occlusion_from_outside_target().ToString()); 3427 } 3428 3429 // The surface has a background blur, so it blurs non-opaque pixels below 3430 // it. 3431 this->VisitContributingSurface(filtered_surface, &occlusion); 3432 { 3433 // The filter is completely occluded, so it should not blur anything and 3434 // reduce any occlusion. 3435 gfx::Rect occlusion_above_surface = gfx::Rect(50, 50, 50, 50); 3436 3437 EXPECT_EQ(occlusion_above_surface.ToString(), 3438 occlusion.occlusion_from_inside_target().ToString()); 3439 EXPECT_EQ(gfx::Rect().ToString(), 3440 occlusion.occlusion_from_outside_target().ToString()); 3441 } 3442 } 3443 }; 3444 3445 ALL_OCCLUSIONTRACKER_TEST( 3446 OcclusionTrackerTestDontReduceOcclusionIfBackgroundFilterIsOccluded); 3447 3448 template <class Types> 3449 class OcclusionTrackerTestReduceOcclusionWhenBackgroundFilterIsPartiallyOccluded 3450 : public OcclusionTrackerTest<Types> { 3451 protected: 3452 explicit 3453 OcclusionTrackerTestReduceOcclusionWhenBackgroundFilterIsPartiallyOccluded( 3454 bool opaque_layers) 3455 : OcclusionTrackerTest<Types>(opaque_layers) {} 3456 void RunMyTest() { 3457 gfx::Transform scale_by_half; 3458 scale_by_half.Scale(0.5, 0.5); 3459 3460 // Make a surface and its replica, each 50x50, that are partially occluded 3461 // by opaque layers which are above them in the z-order. The surface is 3462 // scaled to test that the pixel moving is done in the target space, where 3463 // the background filter is applied, but the surface appears at 50, 50 and 3464 // the replica at 200, 50. 3465 typename Types::ContentLayerType* parent = this->CreateRoot( 3466 this->identity_matrix, gfx::PointF(), gfx::Size(300, 150)); 3467 typename Types::LayerType* filtered_surface = 3468 this->CreateDrawingLayer(parent, 3469 scale_by_half, 3470 gfx::PointF(50.f, 50.f), 3471 gfx::Size(100, 100), 3472 false); 3473 this->CreateReplicaLayer(filtered_surface, 3474 this->identity_matrix, 3475 gfx::PointF(300.f, 0.f), 3476 gfx::Size()); 3477 typename Types::LayerType* above_surface_layer = 3478 this->CreateDrawingLayer(parent, 3479 this->identity_matrix, 3480 gfx::PointF(70.f, 50.f), 3481 gfx::Size(30, 50), 3482 true); 3483 typename Types::LayerType* above_replica_layer = 3484 this->CreateDrawingLayer(parent, 3485 this->identity_matrix, 3486 gfx::PointF(200.f, 50.f), 3487 gfx::Size(30, 50), 3488 true); 3489 typename Types::LayerType* beside_surface_layer = 3490 this->CreateDrawingLayer(parent, 3491 this->identity_matrix, 3492 gfx::PointF(90.f, 40.f), 3493 gfx::Size(10, 10), 3494 true); 3495 typename Types::LayerType* beside_replica_layer = 3496 this->CreateDrawingLayer(parent, 3497 this->identity_matrix, 3498 gfx::PointF(200.f, 40.f), 3499 gfx::Size(10, 10), 3500 true); 3501 3502 // Filters make the layer own a surface. 3503 FilterOperations filters; 3504 filters.Append(FilterOperation::CreateBlurFilter(3.f)); 3505 filtered_surface->SetBackgroundFilters(filters); 3506 3507 // Save the distance of influence for the blur effect. 3508 int outset_top, outset_right, outset_bottom, outset_left; 3509 filters.GetOutsets( 3510 &outset_top, &outset_right, &outset_bottom, &outset_left); 3511 3512 this->CalcDrawEtc(parent); 3513 3514 TestOcclusionTrackerWithClip<typename Types::LayerType, 3515 typename Types::RenderSurfaceType> occlusion( 3516 gfx::Rect(0, 0, 1000, 1000)); 3517 3518 this->VisitLayer(beside_replica_layer, &occlusion); 3519 this->VisitLayer(beside_surface_layer, &occlusion); 3520 this->VisitLayer(above_replica_layer, &occlusion); 3521 this->VisitLayer(above_surface_layer, &occlusion); 3522 3523 // The surface has a background blur, so it blurs non-opaque pixels below 3524 // it. 3525 this->VisitLayer(filtered_surface, &occlusion); 3526 this->VisitContributingSurface(filtered_surface, &occlusion); 3527 3528 // The filter in the surface and replica are partially unoccluded. Only the 3529 // unoccluded parts should reduce occlusion. This means it will push back 3530 // the occlusion that touches the unoccluded part (occlusion_above___), but 3531 // it will not touch occlusion_beside____ since that is not beside the 3532 // unoccluded part of the surface, even though it is beside the occluded 3533 // part of the surface. 3534 gfx::Rect occlusion_above_surface = 3535 gfx::Rect(70 + outset_right, 50, 30 - outset_right, 50); 3536 gfx::Rect occlusion_above_replica = 3537 gfx::Rect(200, 50, 30 - outset_left, 50); 3538 gfx::Rect occlusion_beside_surface = gfx::Rect(90, 40, 10, 10); 3539 gfx::Rect occlusion_beside_replica = gfx::Rect(200, 40, 10, 10); 3540 3541 Region expected_occlusion; 3542 expected_occlusion.Union(occlusion_above_surface); 3543 expected_occlusion.Union(occlusion_above_replica); 3544 expected_occlusion.Union(occlusion_beside_surface); 3545 expected_occlusion.Union(occlusion_beside_replica); 3546 3547 ASSERT_EQ(expected_occlusion.ToString(), 3548 occlusion.occlusion_from_inside_target().ToString()); 3549 EXPECT_EQ(gfx::Rect().ToString(), 3550 occlusion.occlusion_from_outside_target().ToString()); 3551 3552 Region::Iterator expected_rects(expected_occlusion); 3553 Region::Iterator target_surface_rects( 3554 occlusion.occlusion_from_inside_target()); 3555 for (; expected_rects.has_rect(); 3556 expected_rects.next(), target_surface_rects.next()) { 3557 ASSERT_TRUE(target_surface_rects.has_rect()); 3558 EXPECT_EQ(expected_rects.rect(), target_surface_rects.rect()); 3559 } 3560 } 3561 }; 3562 3563 ALL_OCCLUSIONTRACKER_TEST( 3564 OcclusionTrackerTestReduceOcclusionWhenBackgroundFilterIsPartiallyOccluded); 3565 3566 template <class Types> 3567 class OcclusionTrackerTestMinimumTrackingSize 3568 : public OcclusionTrackerTest<Types> { 3569 protected: 3570 explicit OcclusionTrackerTestMinimumTrackingSize(bool opaque_layers) 3571 : OcclusionTrackerTest<Types>(opaque_layers) {} 3572 void RunMyTest() { 3573 gfx::Size tracking_size(100, 100); 3574 gfx::Size below_tracking_size(99, 99); 3575 3576 typename Types::ContentLayerType* parent = this->CreateRoot( 3577 this->identity_matrix, gfx::PointF(), gfx::Size(400, 400)); 3578 typename Types::LayerType* large = this->CreateDrawingLayer( 3579 parent, this->identity_matrix, gfx::PointF(), tracking_size, true); 3580 typename Types::LayerType* small = 3581 this->CreateDrawingLayer(parent, 3582 this->identity_matrix, 3583 gfx::PointF(), 3584 below_tracking_size, 3585 true); 3586 this->CalcDrawEtc(parent); 3587 3588 TestOcclusionTrackerWithClip<typename Types::LayerType, 3589 typename Types::RenderSurfaceType> occlusion( 3590 gfx::Rect(0, 0, 1000, 1000)); 3591 occlusion.set_minimum_tracking_size(tracking_size); 3592 3593 // The small layer is not tracked because it is too small. 3594 this->VisitLayer(small, &occlusion); 3595 3596 EXPECT_EQ(gfx::Rect().ToString(), 3597 occlusion.occlusion_from_outside_target().ToString()); 3598 EXPECT_EQ(gfx::Rect().ToString(), 3599 occlusion.occlusion_from_inside_target().ToString()); 3600 3601 // The large layer is tracked as it is large enough. 3602 this->VisitLayer(large, &occlusion); 3603 3604 EXPECT_EQ(gfx::Rect().ToString(), 3605 occlusion.occlusion_from_outside_target().ToString()); 3606 EXPECT_EQ(gfx::Rect(tracking_size).ToString(), 3607 occlusion.occlusion_from_inside_target().ToString()); 3608 } 3609 }; 3610 3611 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestMinimumTrackingSize); 3612 3613 template <class Types> 3614 class OcclusionTrackerTestScaledLayerIsClipped 3615 : public OcclusionTrackerTest<Types> { 3616 protected: 3617 explicit OcclusionTrackerTestScaledLayerIsClipped(bool opaque_layers) 3618 : OcclusionTrackerTest<Types>(opaque_layers) {} 3619 void RunMyTest() { 3620 gfx::Transform scale_transform; 3621 scale_transform.Scale(512.0, 512.0); 3622 3623 typename Types::ContentLayerType* parent = this->CreateRoot( 3624 this->identity_matrix, gfx::PointF(), gfx::Size(400, 400)); 3625 typename Types::LayerType* clip = this->CreateLayer(parent, 3626 this->identity_matrix, 3627 gfx::PointF(10.f, 10.f), 3628 gfx::Size(50, 50)); 3629 clip->SetMasksToBounds(true); 3630 typename Types::LayerType* scale = this->CreateLayer( 3631 clip, scale_transform, gfx::PointF(), gfx::Size(1, 1)); 3632 typename Types::LayerType* scaled = this->CreateDrawingLayer( 3633 scale, this->identity_matrix, gfx::PointF(), gfx::Size(500, 500), true); 3634 this->CalcDrawEtc(parent); 3635 3636 TestOcclusionTrackerWithClip<typename Types::LayerType, 3637 typename Types::RenderSurfaceType> occlusion( 3638 gfx::Rect(0, 0, 1000, 1000)); 3639 3640 this->VisitLayer(scaled, &occlusion); 3641 3642 EXPECT_EQ(gfx::Rect().ToString(), 3643 occlusion.occlusion_from_outside_target().ToString()); 3644 EXPECT_EQ(gfx::Rect(10, 10, 50, 50).ToString(), 3645 occlusion.occlusion_from_inside_target().ToString()); 3646 } 3647 }; 3648 3649 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestScaledLayerIsClipped) 3650 3651 template <class Types> 3652 class OcclusionTrackerTestScaledLayerInSurfaceIsClipped 3653 : public OcclusionTrackerTest<Types> { 3654 protected: 3655 explicit OcclusionTrackerTestScaledLayerInSurfaceIsClipped(bool opaque_layers) 3656 : OcclusionTrackerTest<Types>(opaque_layers) {} 3657 void RunMyTest() { 3658 gfx::Transform scale_transform; 3659 scale_transform.Scale(512.0, 512.0); 3660 3661 typename Types::ContentLayerType* parent = this->CreateRoot( 3662 this->identity_matrix, gfx::PointF(), gfx::Size(400, 400)); 3663 typename Types::LayerType* clip = this->CreateLayer(parent, 3664 this->identity_matrix, 3665 gfx::PointF(10.f, 10.f), 3666 gfx::Size(50, 50)); 3667 clip->SetMasksToBounds(true); 3668 typename Types::LayerType* surface = this->CreateDrawingSurface( 3669 clip, this->identity_matrix, gfx::PointF(), gfx::Size(400, 30), false); 3670 typename Types::LayerType* scale = this->CreateLayer( 3671 surface, scale_transform, gfx::PointF(), gfx::Size(1, 1)); 3672 typename Types::LayerType* scaled = this->CreateDrawingLayer( 3673 scale, this->identity_matrix, gfx::PointF(), gfx::Size(500, 500), true); 3674 this->CalcDrawEtc(parent); 3675 3676 TestOcclusionTrackerWithClip<typename Types::LayerType, 3677 typename Types::RenderSurfaceType> occlusion( 3678 gfx::Rect(0, 0, 1000, 1000)); 3679 3680 this->VisitLayer(scaled, &occlusion); 3681 this->VisitLayer(surface, &occlusion); 3682 this->VisitContributingSurface(surface, &occlusion); 3683 3684 EXPECT_EQ(gfx::Rect().ToString(), 3685 occlusion.occlusion_from_outside_target().ToString()); 3686 EXPECT_EQ(gfx::Rect(10, 10, 50, 50).ToString(), 3687 occlusion.occlusion_from_inside_target().ToString()); 3688 } 3689 }; 3690 3691 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestScaledLayerInSurfaceIsClipped) 3692 3693 template <class Types> 3694 class OcclusionTrackerTestCopyRequestDoesOcclude 3695 : public OcclusionTrackerTest<Types> { 3696 protected: 3697 explicit OcclusionTrackerTestCopyRequestDoesOcclude(bool opaque_layers) 3698 : OcclusionTrackerTest<Types>(opaque_layers) {} 3699 void RunMyTest() { 3700 typename Types::ContentLayerType* root = this->CreateRoot( 3701 this->identity_matrix, gfx::Point(), gfx::Size(400, 400)); 3702 typename Types::ContentLayerType* parent = this->CreateDrawingLayer( 3703 root, this->identity_matrix, gfx::Point(), gfx::Size(400, 400), true); 3704 typename Types::LayerType* copy = this->CreateLayer(parent, 3705 this->identity_matrix, 3706 gfx::Point(100, 0), 3707 gfx::Size(200, 400)); 3708 this->AddCopyRequest(copy); 3709 typename Types::LayerType* copy_child = this->CreateDrawingLayer( 3710 copy, 3711 this->identity_matrix, 3712 gfx::PointF(), 3713 gfx::Size(200, 400), 3714 true); 3715 this->CalcDrawEtc(root); 3716 3717 TestOcclusionTrackerWithClip<typename Types::LayerType, 3718 typename Types::RenderSurfaceType> occlusion( 3719 gfx::Rect(0, 0, 1000, 1000)); 3720 3721 this->VisitLayer(copy_child, &occlusion); 3722 EXPECT_EQ(gfx::Rect().ToString(), 3723 occlusion.occlusion_from_outside_target().ToString()); 3724 EXPECT_EQ(gfx::Rect(200, 400).ToString(), 3725 occlusion.occlusion_from_inside_target().ToString()); 3726 3727 // CopyRequests cause the layer to own a surface. 3728 this->VisitContributingSurface(copy, &occlusion); 3729 3730 // The occlusion from the copy should be kept. 3731 EXPECT_EQ(gfx::Rect().ToString(), 3732 occlusion.occlusion_from_outside_target().ToString()); 3733 EXPECT_EQ(gfx::Rect(100, 0, 200, 400).ToString(), 3734 occlusion.occlusion_from_inside_target().ToString()); 3735 } 3736 }; 3737 3738 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestCopyRequestDoesOcclude) 3739 3740 template <class Types> 3741 class OcclusionTrackerTestHiddenCopyRequestDoesNotOcclude 3742 : public OcclusionTrackerTest<Types> { 3743 protected: 3744 explicit OcclusionTrackerTestHiddenCopyRequestDoesNotOcclude( 3745 bool opaque_layers) 3746 : OcclusionTrackerTest<Types>(opaque_layers) {} 3747 void RunMyTest() { 3748 typename Types::ContentLayerType* root = this->CreateRoot( 3749 this->identity_matrix, gfx::Point(), gfx::Size(400, 400)); 3750 typename Types::ContentLayerType* parent = this->CreateDrawingLayer( 3751 root, this->identity_matrix, gfx::Point(), gfx::Size(400, 400), true); 3752 typename Types::LayerType* hide = this->CreateLayer( 3753 parent, this->identity_matrix, gfx::Point(), gfx::Size()); 3754 typename Types::LayerType* copy = this->CreateLayer( 3755 hide, this->identity_matrix, gfx::Point(100, 0), gfx::Size(200, 400)); 3756 this->AddCopyRequest(copy); 3757 typename Types::LayerType* copy_child = this->CreateDrawingLayer( 3758 copy, this->identity_matrix, gfx::PointF(), gfx::Size(200, 400), true); 3759 3760 // The |copy| layer is hidden but since it is being copied, it will be 3761 // drawn. 3762 hide->SetHideLayerAndSubtree(true); 3763 3764 this->CalcDrawEtc(root); 3765 3766 TestOcclusionTrackerWithClip<typename Types::LayerType, 3767 typename Types::RenderSurfaceType> occlusion( 3768 gfx::Rect(0, 0, 1000, 1000)); 3769 3770 this->VisitLayer(copy_child, &occlusion); 3771 EXPECT_EQ(gfx::Rect().ToString(), 3772 occlusion.occlusion_from_outside_target().ToString()); 3773 EXPECT_EQ(gfx::Rect(200, 400).ToString(), 3774 occlusion.occlusion_from_inside_target().ToString()); 3775 3776 // CopyRequests cause the layer to own a surface. 3777 this->VisitContributingSurface(copy, &occlusion); 3778 3779 // The occlusion from the copy should be dropped since it is hidden. 3780 EXPECT_EQ(gfx::Rect().ToString(), 3781 occlusion.occlusion_from_outside_target().ToString()); 3782 EXPECT_EQ(gfx::Rect().ToString(), 3783 occlusion.occlusion_from_inside_target().ToString()); 3784 } 3785 }; 3786 3787 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestHiddenCopyRequestDoesNotOcclude) 3788 3789 template <class Types> 3790 class OcclusionTrackerTestEmptyEventLayerDoesNotOcclude 3791 : public OcclusionTrackerTest<Types> { 3792 protected: 3793 explicit OcclusionTrackerTestEmptyEventLayerDoesNotOcclude( 3794 bool opaque_layers) 3795 : OcclusionTrackerTest<Types>(opaque_layers) {} 3796 void RunMyTest() { 3797 typename Types::ContentLayerType* root = this->CreateRoot( 3798 this->identity_matrix, gfx::Point(), gfx::Size(400, 400)); 3799 typename Types::ContentLayerType* empty_layer = this->CreateDrawingLayer( 3800 root, this->identity_matrix, gfx::Point(), gfx::Size(200, 200), true); 3801 this->SetDrawsContent(empty_layer, false); 3802 empty_layer->SetTouchEventHandlerRegion(gfx::Rect(10, 10, 10, 10)); 3803 3804 this->CalcDrawEtc(root); 3805 3806 TestOcclusionTrackerWithClip<typename Types::LayerType, 3807 typename Types::RenderSurfaceType> occlusion( 3808 gfx::Rect(0, 0, 1000, 1000), false); 3809 3810 this->VisitLayer(empty_layer, &occlusion); 3811 3812 EXPECT_EQ(gfx::Rect().ToString(), 3813 occlusion.occlusion_from_outside_target().ToString()); 3814 EXPECT_EQ(gfx::Rect().ToString(), 3815 occlusion.occlusion_from_inside_target().ToString()); 3816 } 3817 }; 3818 3819 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestEmptyEventLayerDoesNotOcclude) 3820 3821 } // namespace 3822 } // namespace cc 3823